विकिपिडिया newiki https://ne.wikipedia.org/wiki/%E0%A4%AE%E0%A5%81%E0%A4%96%E0%A5%8D%E0%A4%AF_%E0%A4%AA%E0%A5%83%E0%A4%B7%E0%A5%8D%E0%A4%A0 MediaWiki 1.47.0-wmf.6 first-letter मीडिया विशेष वार्तालाप प्रयोगकर्ता प्रयोगकर्ता वार्ता विकिपिडिया विकिपिडिया वार्ता चित्र चित्र वार्ता मीडियाविकि मीडियाविकि वार्ता ढाँचा ढाँचा वार्ता मद्दत मद्दत वार्ता श्रेणी श्रेणी वार्ता पोर्टल पोर्टल वार्ता मस्यौदा मस्यौदा वार्ता TimedText TimedText talk मोड्युल मोड्युल वार्तालाप Event Event talk हिन्दु धर्म 0 826 1361157 1345864 2026-06-11T12:26:20Z RANGAVANTHIYAR 79279 1361157 wikitext text/x-wiki {{हिन्दु धर्म बाकस}} '''हिन्दु धर्म''' एक [[धर्म]] हो, जसलाई प्रायः धार्मिक परम्पराहरू र [[दार्शनिक विद्यालय]]हरूको सङ्ग्रहको रूपमा वर्णन गरिएको छ जुन [[भारतीय उपमहाद्वीप]]मा उत्पत्ति भएको हो। [[संस्कृत]]मा हिन्दु धर्मको ऐतिहासिक नाम '''सनातन धर्म''' हो जसको अर्थ "शाश्वत धर्म", "अनन्त मार्ग" वा "अनन्त कानून" हो। हिन्दु धर्मको जरा [[वैदिक सभ्यता|वैदिक]], [[सिन्धु घाटीको सभ्यता|सिन्धु घाटी]] र [[द्रविड]] सभ्यताहरूमा छ, त्यसैले हिन्दु धर्मलाई [[पृथ्वी|संसार]]को सबैभन्दा पुरानो धर्म भनिन्छ। [[धर्मशास्त्र|धर्म]], [[कर्म]], [[संसार (बौद्ध)|संसार]], [[माया (हिन्दु धर्म)|माया]], [[मोक्ष]] र [[योग]] जस्ता धार्मिक पदहरूले गर्दा हिन्दु धर्मलाई विशिष्ट मानिन्छ। हिन्दु धर्ममा ठुलो सङ्ख्यामा [[धर्मशास्त्र|शास्त्र]]हरू छन्, जुन दुई मुख्य कोटीहरूमा पर्छन्: [[श्रुति]] र [[स्मृति]]। महत्वपूर्ण हिन्दु ग्रन्थहरू [[वेद]], [[उपनिषद्]], [[पुराण]], [[रामायण]], [[महाभारत]], [[श्रीमद्भगवद गीता]] र [[आगम]]हरू हुन्। हिन्दु धर्म १ अर्ब ५० करोड भन्दा बढी मानिसहरू द्वारा अभ्यास गरिएको छ - हिन्दु धर्म संसारमा तेस्रो ठुलो धर्म हो। [[भारत]] र [[नेपाल]]को [[जनसङ्ख्या]]को अधिकांश हिस्सा हिन्दुहरू छन्। जस मध्ये ९६% [[दक्षिण एसिया]]मा छन्। [[बङ्गलादेश]], [[श्रीलङ्का]], [[पाकिस्तान]], [[इन्डोनेसिया]], [[मलेसिया]], [[सिङ्गापुर]], [[मौरिसस]], [[फिजी]], [[सुरिनाम]], [[गयाना]], [[ट्रिनिडाड र टोबागो]], [[संयुक्त अधिराज्य]], [[क्यानडा]] र [[संयुक्त राज्य अमेरिका]] जस्ता देशहरूमा हिन्दु धर्मका अनुयायीहरूको उल्लेखनीय सङ्ख्या पाइन्छ। == नाम == {{Further|हिन्दुहरू}} हिन्दु शब्द [[हिन्द-आर्य भाषाहरू|हिन्द-आर्य]]/[[संस्कृत]] मूल सिन्धुबाट आएको हो, जसलाई [[भारतीय उपमहाद्वीप]]को [[उत्तर-पश्चिम प्रदेश|उत्तरपश्चिमी]] भागमा रहेको [[सिन्धु नदी]]को नाम मानिन्छ।<ref>{{Cite web|url=https://pahilopost.com/content/-6839.html|title=हिन्दु कि सनातन वैदिक धर्म?|last=जोशी|first=सत्यराज|date=३१ साउन २०७२|website=पहिलो पोस्ट|accessdate=१५ मङ्सिर २०७९}}</ref><ref>{{Cite web|url=https://nagariknews.nagariknetwork.com/opinion/114394-1483935480.html|title=‘हिन्दु’को परिचय|last=शर्मा|first=डा तारानाथ|date=२५ पुस २०७३|website=नागरीक|language=ne|accessdate=१५ मङ्सिर २०७९}}</ref> [[संस्कृत]]मा, सनातन धर्मले लगभग "अनन्त [[कानून]]" वा कम शाब्दिक रूपमा, "अनन्त मार्ग" लाई अनुवाद गरिन्छ। [[पाली भाषा]]मा, समकक्ष शब्द ''धम्मो सनातनो'' हो।<ref name="harvey20012">so {{cite book|author=Harvey, Andrew|title=Teachings of the Hindu Mystics|publisher=Shambhala|location=Boulder|year=2001|pages=xiii|isbn=1-57062-449-6}}). See also [[René Guénon]], ''Introduction to the Study of the Hindu Doctrines'' (1921 ed.), Sophia Perennis, ISBN 0-900588-74-8, part III, chapter 5 "The Law of Manu", p. 146. On the meaning of the word "Dharma", see also [[René Guénon]], ''Studies in Hinduism'', Sophia Perennis, ISBN 0-900588-69-3, chapter 5, p. 45</ref> [[नेपाली भाषा]]मा, संस्कृत [[तत्सम]] ''धर्म'' शब्द लाई (यसको संस्कृत अर्थ "कानून" वा अधिक शाब्दिक रूपमा "जुन समर्थन गर्दछ; के दृढतापूर्वक स्थापित छ") "[[धर्म]]" (निष्ठा) को रूपमा प्रयोग गरिन्छ।<ref name="harvey2001">so {{cite book|author=Harvey, Andrew|title=Teachings of the Hindu Mystics|publisher=Shambhala|location=Boulder|year=2001|pages=xiii|isbn=1-57062-449-6}}). See also [[René Guénon]], ''Introduction to the Study of the Hindu Doctrines'' (1921 ed.), Sophia Perennis, ISBN 0-900588-74-8, part III, chapter 5 "The Law of Manu", p. 146. On the meaning of the word "Dharma", see also [[René Guénon]], ''Studies in Hinduism'', Sophia Perennis, ISBN 0-900588-69-3, chapter 5, p. 45</ref> == परिभाषा == [[चित्र:Aum Om navy blue circle coral.svg|thumb|हिन्दु धर्ममा [[ૐ]] लाई धार्मिक प्रतीकको रूपमा प्रयोग गरिन्छ]] हिन्दु धर्म शब्दले ढाकेको परम्परा र विचारहरूको व्यापक दायराको कारण, एक व्यापक परिभाषामा पुग्न गाह्रो छ।<ref name=":0">{{Cite web|url=https://nepalpatra.com/religion-culture/90312/|title=हिन्दु कसलाई भन्ने?|website=नेपालपत्र|accessdate=2022-12-01}}{{Dead link|date=March 2026 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> हिन्दु धर्मले [[अध्यात्म]] र [[परम्परा]]हरूमा विचारहरूको विविधता समावेश गर्दछ, तर कुनै चर्चको आदेश छैन, कुनै निर्विवाद धार्मिक अधिकारीहरू छैनन्, कुनै शासक निकाय छैन, कुनै अगमवक्ता(हरू) वा कुनै एक पवित्र पुस्तकहरू छैनन्; हिन्दुहरूले बहुदेववादी, सर्वधर्मवादी, सर्वधर्मवादी, पाण्डेइस्टिक, हेनोथेस्टिक, एकेश्वरवादी, अद्वैतवादी, [[अज्ञेयवाद|अज्ञेयवादी]], [[नास्तिक]] वा [[मानवता|मानवतावादी]] हुन रोज्न सक्छन्।<ref>MK Gandhi, ''[http://www.mkgandhi.org/ebks/essence_of_hinduism.pdf The Essence of Hinduism] {{Webarchive|url=https://web.archive.org/web/20150724045756/http://www.mkgandhi.org/ebks/essence_of_hinduism.pdf|date=24 July 2015}}'', Editor: VB Kher, Navajivan Publishing"</ref><ref>{{Cite book|title=Encyclopedia of Violence, Peace and Conflict|publisher=Academic Press|year=2008|isbn=978-0-12-369503-1|editor-last=Kurtz|editor-first=Lester}}</ref> हिन्दु धर्मलाई धर्म, धार्मिक परम्परा, धार्मिक विश्वासको एक सेट, र "जीवन पद्धति" को रूपमा विभिन्न रूपमा परिभाषित गरिएको छ।<ref name=":0" /> === प्रकारहरू === * हिन्दु धर्मको सबैभन्दा पुरानो रूप लोक विश्वास हो, जुन स्थानीय [[देवता]]हरूको [[पूजा]] र देवता रूपहरू द्वारा विशेषता हो। * [[वैदिक सभ्यता|वैदिक]]: वैदिक शास्त्रहरूमा आधारित, जसमध्ये सबैभन्दा महत्त्वपूर्ण र प्राचीन [[ऋग्वेद]] मानिन्छ। * [[वेदान्त|वेदान्तिक]]: [[उपनिषद्|उपनिषद]]हरूमा आधारित छ - चार [[वेद]]हरूसँगै धार्मिक र दार्शनिक ग्रंथहरू। * [[योग]]: योगको दिशालाई [[पतञ्जलि]]को योग सूत्रमा प्रस्तुत * [[भक्ति]] ([[भगवान]]को मायालु भक्ति सेवा): हिन्दु धर्ममा भक्तिको मुख्य [[वैष्णव]] परम्परा हो यस अवधारणाको ढाँचा भित्र पहिचान गरिएका अन्य समूहहरूमा एकदम अन्तर्निहित छ। === सम्प्रदाय === {{Further|सम्प्रदाय}} हिन्दु धर्ममा कुनै पनि सामान्य, केन्द्रीय सिद्धान्त छैन जुन सबै हिन्दु परम्पराहरूको लागि आधिकारिक हो, र धेरै हिन्दुहरूले आफूलाई कुनै पनि विशेष परम्परासँग सम्बन्धित ठान्दैनन्। तथापि, विद्वानहरूले आधुनिक हिन्दु धर्ममा चार मुख्य दिशाहरू छुट्याएका छन्:<ref name="junemcdaniel6">June McDaniel "Hinduism", in {{Cite book|last=Corrigan|first=John|title=The Oxford Handbook of Religion and Emotion|publisher=Oxford University Press|year=2007|isbn=978-0-19-517021-4|pages=52–53}}</ref><ref>{{Cite web|url=https://www.eadarsha.com/nep/article/%e0%a4%b9%e0%a4%bf%e0%a4%a8%e0%a5%8d%e0%a4%a6%e0%a5%82-%e0%a4%a7%e0%a4%b0%e0%a5%8d%e0%a4%ae-%e0%a4%b0-%e0%a4%af%e0%a4%b8%e0%a4%95%e0%a4%be-%e0%a4%b8%e0%a4%ae%e0%a5%8d%e0%a4%aa%e0%a5%8d%e0%a4%b0/|title=हिन्दु धर्म र यसका सम्प्रदायहरू|last=|first=|website=आदर्श समाज|accessdate=2022-12-01}}{{Dead link|date=April 2025 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> * [[शैव|शैव (]][[शिव]]) * [[वैष्णव|वैष्णव (]][[विष्णु]]) * शाक्त ([[देवी]]) * [[स्मार्त]] (पाँच देवतालाई समान) हिन्दु धर्मले असंख्य दिव्य प्राणीहरूलाई पनि स्वीकार गर्दछ, धेरै हिन्दुहरूले [[देवता]]हरूलाई एकल अवैयक्तिक निरपेक्ष वा परम वास्तविकता वा [[ईश्वर]]को रूप वा रूपहरू मान्छन, जबकि केही [[हिन्दुहरू]]ले एक विशिष्ट देवताले सर्वोच्चलाई प्रतिनिधित्व गर्दछ र विभिन्न देवताहरू यस सर्वोच्चको निम्न अभिव्यक्तिहरू हुन् भनी विश्वास गरिन्छ।<ref>{{Cite web|url=https://www.newsofnepal.com/2020/06/15/326065/|title=के हो धार्मिक सम्प्रदाय ?|website=नेपाल समाचारपत्र|language=|accessdate=2022-12-01}}</ref> == विश्वासहरू == हिन्दु विश्वासका प्रमुख विषयवस्तुहरूमा धर्म (नैतिकता/कर्तव्यहरू), संसार (आकांक्षाहरू र परिणामस्वरूप जन्म, जीवन, मृत्यु र [[पुनर्जन्म (बौद्ध धर्म)|पुनर्जन्म]]), [[कर्म]] (कार्य, अभिप्राय, र परिणामहरू) समावेश छन् (तर यसमा सीमित छैनन्), [[मोक्ष]] (लग्न र संसारबाट मुक्ति), र विभिन्न योगहरू (मार्ग वा अभ्यासहरू)। === पुरुषार्थ === {{Further|पुरुषार्थ}} [[चित्र:Reincarnation AS.jpg|thumb|पुनर्जन्मको प्रतिनिधित्व]] * '''[[धर्म]]''': हिन्दु धर्ममा [[धर्म]]लाई मानवको प्रमुख लक्ष्य मानिन्छ। धर्मको अवधारणाले [[जीवन]] र [[ब्रह्माण्ड]]लाई सम्भव बनाउने क्रम, र कर्तव्य, [[अधिकार]], [[कानून]], आचरण, सद्गुण र "जीवनको सही तरिका" समावेश गर्ने व्यवहारहरू समावेश गर्दछ। * [[अर्थशास्त्र (ग्रन्थ)|'''अर्थ''']]: अर्थ भनेको जीविकोपार्जन, दायित्व र आर्थिक समृद्धिका लागि धनको वस्तुगत र सद्गुणको खोज हो। यो [[राजनीति|राजनीतिक]] जीवन, [[कूटनीति]], र भौतिक कल्याण समावेशी छ। अर्थ अवधारणामा सबै "जीवनका साधनहरू", गतिविधिहरू र स्रोतहरू समावेश [https://daark.ae/ छन्] जसले व्यक्तिलाई राज्यमा हुन सक्षम बनाउँछ, [[धन]], क्यारियर र वित्तीय सुरक्षा। * [[कामसूत्र|'''काम''']]: काम भनेको चाहना, इच्छा, जोश, लालसा, इन्द्रियको आनन्द, जीवनको सौन्दर्यपूर्ण आनन्द, स्नेह, वा [[प्रेम]], [[यौन]] अर्थ सहित वा बिना। * '''[[मोक्ष]]''': मोक्ष हिन्दु धर्ममा परम, सबैभन्दा महत्त्वपूर्ण लक्ष्य हो। एक अर्थमा, मोक्ष [[दुख|दुःख]], कष्ट र संसार (जन्म-पुनर्जन्म चक्र) बाट मुक्तिसँग सम्बन्धित अवधारणा हो। यस एस्केटोलोजिकल चक्रबाट मुक्ति, जीवन पछि, विशेष गरी हिन्दु धर्मका [[ईश्वर]]वादी विद्यालयहरूमा मोक्ष भनिन्छ। * '''[[कर्म]]''': कर्मले शाब्दिक रूपमा कार्य, काम, वा कर्मको रूपमा अनुवाद गर्दछ, र "कारण र प्रभावको नैतिक कानून" को [[वैदिक सभ्यता|वैदिक]] सिद्धान्तलाई पनि जनाउँछ। यो [[जन्म]], [[जीवन]], [[अन्तिम संस्कार|मृत्यु]] र [[पुनर्जन्म (बौद्ध धर्म)|पुनर्जन्म]]को चक्रलाई [[संसार (बौद्ध)|संसार]] भनिन्छ। मोक्षको माध्यमबाट संसारबाट [[मुक्ति]]ले दिगो सुख र [[शान्ति]] सुनिश्चित गर्ने विश्वास गरिन्छ। === योग === {{Further|योग|राजयोग|श्रीमद्भगवद गीता|पतञ्जलि योगसूत्र}} [[चित्र:Shiva Bangalore.jpg|thumb|योग [[ध्यान]]मा भगवान [[शिव]]को मूर्ति]] हिन्दुका लागि जीवनको अन्तिम लक्ष्य जेसुकै होस्, यो लक्ष्य प्राप्त गर्नका लागि [[ऋषि]]हरूले दिएका धेरै [[योग]] विधिहरू छन्। विभिन्न प्रकारका योगको वर्णन गर्ने आधारभूत ग्रन्थहरूमा [[श्रीमद्भगवद गीता]], [[पतञ्जलि योगसूत्र|योग सूत्र]], हठयोग प्रदीपिका र [[उपनिषद्|उपनिषद]]हरू समावेश छन्। योगका मुख्य प्रकारहरू, जसलाई अनुसरण गरेर उच्चतम आध्यात्मिक पूर्णता (मोक्ष वा समाधि) प्राप्त गर्न सम्भव छ: * [[भक्ति योग|'''भक्ति योग''']]: प्रेम र भक्ति मार्ग * '''[[कर्म योग]]''': सही कार्यको बाटो * '''[[राज योग]]''': ध्यान को मार्ग * '''[[ज्ञान योग]]''': ज्ञान वा बुद्धिको मार्ग === ईश्वरको अवधारणा === {{Further|हिन्दु धर्ममा ईश्वर|अवतार|देवी-देवता}} धेरै हिन्दुहरूले [[ब्रह्माण्ड]]को सृष्टि गर्ने, कायम राख्ने र नष्ट गर्ने ईश्वरीय वास्तविकतालाई स्वीकार गर्छन्, तर केही हिन्दु सम्प्रदायहरूले यो विचारलाई अस्वीकार गर्छन्। धेरैजसो हिन्दुहरू एक विश्वव्यापी [[ईश्वर]]मा विश्वास गर्छन् जो एकै साथ प्रत्येक जीवित [[प्राणी]] भित्र छ र जसलाई विभिन्न तरिकामा सम्पर्क गर्न सकिन्छ। [[पुराण]] र हिन्दु महाकाव्यहरू "[[महाभारत]]" र "[[रामायण]]"ले [[समाज]]मा धर्मको पुनर्स्थापना गर्न र मानवतालाई [[मोक्ष]] (जन्म र मृत्युको चक्रबाट मुक्ति) तर्फ लैजानको लागि कसरी देवताहरू मानव रूपमा [[पृथ्वी]]मा अवतरण गर्छन् भन्ने बारे धेरै कथाहरू वर्णन गर्दछ। यस्ता [[देवता]]का अवतारहरूलाई "[[अवतार]]" भनिन्छ। [[विष्णु]]का सबैभन्दा महत्त्वपूर्ण अवतारहरू (जसलाई [[वैष्णव]] अधिकांश अनुयायीहरूले ईश्वरको मूल रूप मान्छन्) [[कृष्ण]] र [[श्रीराम अवतार|राम]] हुन्। हिन्दु धर्मको अधिकांश वैष्णव परम्पराहरूमा, कृष्णलाई विष्णुको सबैभन्दा पूर्ण अवतार मानिन्छ, जसमा व्यक्तिगत निरपेक्षताका सबै दिव्य गुणहरू प्रकट हुन्छन्। [[गौडिय वैष्णव सम्प्रदाय|गौडिया वैष्णववाद]], पुष्टिमार्ग र निम्बार्क सम्प्रदाय जस्ता वैष्णववादका प्रवाहहरूमा, कृष्णलाई स्वयं-भगवानको रूपमा [[पूजा]] गरिन्छ। === आध्यात्मिक साधनाको अन्तिम लक्ष्य === आध्यात्मिक साधनाको अन्तिम लक्ष्यलाई "[[मोक्ष]]", "[[निर्वाण]]" वा "[[समाधि|समाधी]]" जस्ता शब्दहरूद्वारा जनाइएको छ, र हिन्दु धर्मका विभिन्न दिशाहरूलाई विभिन्न तरिकाले बुझिन्छ: * भगवान संग एकता को जागरूकता * [[ईश्वर|परमेश्वर]]सँगको अनन्त सम्बन्धको जागरूकता र उहाँको [[वैकुण्ठ|निवासमा]] फर्कन * परमेश्वरको शुद्ध प्रेमको उपलब्धिहरू * सबैको एकताको चेतना * आफ्नो साँचो आत्म महसुस गर्दै * पूर्ण शान्ति प्राप्त गर्दै * भौतिक इच्छाहरूबाट पूर्ण स्वतन्त्रता === स्वर्ग र नरकको अवधारणा === {{Further|लोक|त्रैलोक्य}} हिन्दु धर्मको [[पुराण]] साहित्यमा [[नरक]] र [[स्वर्ग]]को अवधारणा प्रस्तुत गरिएको छ। यसले अनगिन्ती स्वर्गीय र नरकीय लोकहरू ([[ग्रह]] वा अस्तित्वको विमानहरू) को [[वर्ण|वर्णन]] गर्दछ, जहाँ मृतकहरूलाई उनीहरूले गरेका राम्रो वा पापपूर्ण कामहरूको आधारमा पुरस्कृत वा सजाय दिइन्छ। आत्माको नरकीय सूक्ष्म क्षेत्रहरूमा झरेको [[आत्मा (हिन्दु धर्म)|आत्मा]]लाई खाना र पानीको बलिदानद्वारा त्यहाँबाट उद्धार गर्न सकिन्छ, जुन अन्तिम [[अवतार]]मा यसका छोराछोरी र नातिनातिनाहरूले गर्नु पर्छ। स्वर्गीय वा नरकीय ग्रहहरूमा निश्चित समय बिताएपछि, आत्मा विभिन्न भौतिक तत्वहरू ([[पृथ्वी]], [[पानी|जल]], [[हावा|वायु]], [[आगो|अग्नि]], ईथर र अन्य सूक्ष्म तत्वहरू) मार्फत जान्छ र अन्तमा, ८,४००,००० प्रकारका [[शरीर]]हरू मध्ये एकमा [[पुनर्जन्म (बौद्ध धर्म)|पुनर्जन्म]] हुन्छ। == इतिहास == {{Main page|हिन्दु धर्मको इतिहास}}हिन्दु धर्मको इतिहास [[फलाम युग]] देखि [[भारतीय उपमहाद्वीप]]मा धर्मको विकाससँग मेल खान्छ, यसका केही परम्पराहरू कांस्य युग [[सिन्धु घाटीको सभ्यता]] जस्ता प्रागैतिहासिक धर्महरूमा फर्किएका छन्। यसरी यसलाई संसारको "सबैभन्दा पुरानो धर्म" भनिन्छ। यसमा एक अज्ञात मातृदेवीको मूर्ति, [[शिव]] [[पशुपतिनाथ मन्दिर|पशुपति]] आदी जस्तो देवताहरूको मुद्राहरू, लिंग, पीपलको पूजा, इत्यादि प्रमुख छन्।विद्वानहरूले हिन्दु धर्मलाई विभिन्न [[भारतीय संस्कृति]] र परम्पराहरूको संश्लेषणको रूपमा मान्दछन्, जसमा विभिन्न जराहरू छन् र कुनै एकल संस्थापक छैन।[[चित्र:Kailash Tibet edited.jpg|thumb|[[तिब्बत]]को पवित्र [[कैलाश पर्वत]]लाई [[शिव]]को आध्यात्मिक निवास मानिन्छ]] == पवित्र ग्रन्थहरू == {{Main article|हिन्दु धर्मग्रन्थ|हिन्दु दर्शन}} शताब्दीयौंदेखि, हिन्दु धर्मका पवित्र शास्त्रहरू पद्य रूपमा मौखिक रूपमा प्रसारित गरिएको थियो, जुन स्मरणको सुविधाको लागि प्रयोग गरिएको थियो। [[ऋषि]]हरूले [[शिक्षा]]हरूलाई सिद्ध गरेका छन् र [[धर्मशास्त्र]]को क्यानन विस्तार गरेका छन्। उत्तर-[[वैदिक सभ्यता|वैदिक]] र आधुनिक हिन्दु धर्मका केही परम्पराहरूमा, शास्त्रहरूलाई शाब्दिक रूपमा व्याख्या गरिएको छैन - तिनीहरूमा निहित नैतिक र रूपक अर्थलाई बढी महत्त्व दिइन्छ। अधिकांश पवित्र ग्रन्थहरू संस्कृतमा लेखिएका छन्। उनीहरूलाई [[श्रुति]] र [[स्मृति]] गरी दुई वर्गमा विभाजन गरिएको छ। === श्रुति === {{Main article|श्रुति}} [[चित्र:Rigveda MS2097.jpg|200px|thumb|[[ऋग्वेद]], संसारको सबैभन्दा पुरानो धार्मिक ग्रन्थहरू मध्ये एक।]] "श्रुति" चार [[वेद]]हरूको सम्बन्धमा प्रयोग गरिन्छ, जुन हिन्दु धर्मको सबैभन्दा पुरानो पवित्र ग्रन्थ मानिन्छ। धेरैजसो हिन्दुहरूले वेदहरूलाई मानिसद्वारा सृष्टि नगरिएको, अनन्त ईश्वरीय रूपमा प्रकट गरिएका शास्त्रहरू जुन पवित्र ऋषिहरूको मध्यस्थता मार्फत मानवजातिलाई दिइएको थियो भनेर सम्मान गर्छन्। धेरै हिन्दुहरूले विश्वास गर्छन् कि वेदहरूमा उल्लिखित आध्यात्मिक सत्यहरू अनन्त छन्, [[इतिहास]]भरि उनीहरूलाई नयाँ रूपहरूमा व्यक्त गरिएको छ र विभिन्न तरिकामा व्याख्या गरिएको छ। श्रुतिमा चार वेदहरू छन्: [[ऋग्वेद]], [[सामवेद]], [[यजुर्वेद]], [[अथर्ववेद]]। प्रत्येक वेद चार भागमा विभाजित छ: [[संहितापाठ|संहिता]], [[ब्राह्मणम्]], [[आरण्यक]] र [[उपनिषद्]]। === स्मृति === {{Main article|स्मृति}} [[चित्र:Krishna Arjuna Gita.jpg|thumb|left|भगवान [[कृष्ण]]ले [[अर्जुन]]लाई [[श्रीमद्भगवद गीता]] भन्नुहुन्छ]] स्मृतिहरूमध्ये सबैभन्दा महत्त्वपूर्ण महाकाव्य [[महाभारत]] र [[रामायण]] हुन्। [[श्रीमद्भगवद गीता]] महाभारतको अंश हो र हिन्दु धर्मका सबै पवित्र ग्रन्थहरूमा सबैभन्दा व्यापक रूपमा ज्ञात र अध्ययन गरिएको मानिन्छ। यसमा [[कुरुक्षेत्र युद्ध|कुरुक्षेत्रको महान युद्ध]] सुरु हुनु अघि योद्धा राजकुमार [[अर्जुन]]लाई [[कृष्ण]]को दार्शनिक निर्देशनहरू छन्। दुबै हिन्दुहरू र धेरै पश्चिमी [[वैज्ञानिक]]हरू र दार्शनिकहरूले श्रीमद्भगवद गीतामा सबै वेदहरूको मुख्य सार समावेश गर्दछ भन्ने विश्वास गर्छन्। स्मृति वर्गमा [[पुराण]]हरू पनि समावेश छन्, जसले हिन्दु विश्वास र [[दर्शन]]लाई सजिलो र पहुँचयोग्य रूपमा प्रस्तुत गर्दछ, र धेरै फरक कथाहरू समावेश गर्दछ। त्यहाँ छुट्टै [[धर्मशास्त्र|शास्त्र]]हरू पनि छन् जुन हिन्दु धर्ममा केही निर्देशनहरू मात्र पछ्याइएको छ, जसमा [[देवीमाहात्म्य]], [[तन्त्र]], [[पतञ्जलि योगसूत्र|योग सूत्र]], [[शिवसूत्र]]हरू र [[आगम]]हरू समावेश छन्। साथै एक महत्त्वपूर्ण पाठ [[मनुस्मृति]] हो, जसले वर्णाश्रमका कानून र सामाजिक मान्यताहरू वर्णन गर्दछ। == अभ्यासहरू == === मन्दिर र मूर्ति === {{मुख्य|मन्दिर|मूर्ति}}हिन्दु धर्ममा [[देवता]]हरूको [[मूर्ति]]द्वारा पूजा गरिन्छ। मूर्तिको मुख्य भूमिका देवतासँग गहिरो व्यक्तिगत सम्बन्ध बनाउनु हो। मूर्तिलाई देवताको रूप मानिन्छ, उहाँभन्दा भिन्न छैन। देवताको एक गुण सर्वव्यापी भएकोले मानिसलाई आफ्नो आराधना गर्न सजिलो होस् भनेर देवता पनि मूर्तिको माध्यमबाट प्रकट हुन्छन्। [[पद्म पुराण]]मा, विशेष गरी, यो भनिएको छ कि मूर्तिलाई साधारण ढुङ्गा वा काठको टुक्रा सम्झनु हुँदैन - मूर्ति [[भगवान]]को प्रत्यक्ष रूप हो। === शुभ प्रतिक === {{मुख्य|ओम|स्वस्तिक|टीका}} [[चित्र:Three basic Hindu symbols.jpg|thumb|हिन्दु प्रतीकहरू]] हिन्दु धर्ममा प्रत्येक प्रतीकको यसको पवित्र अर्थ हुन्छ। अक्षर "[[ૐ]] (ओम)" (जसले [[ब्रह्म|परब्रह्म]]को प्रतीक हो) र [[स्वस्तिक]]को चिह्न (कल्याणको प्रतिनिधित्व गर्ने) सबै हिन्दु धर्मको पवित्र प्रतीक मान्न सकिन्छ। जबकि, उदाहरणका लागि, [[टीका|तिलक]]का विभिन्न रूपहरूले विभिन्न हिन्दु सम्प्रदायका अनुयायीहरूलाई पहिचान गर्न मद्दत गर्दछ। त्यहाँ धेरै प्रतीकहरू छन् जुन निश्चित देवताहरूसँग चिनिन्छन्; यसमा [[कमल]], [[चक्र]] र [[वीणा]] समावेश छन्। === संस्कार === धेरै हिन्दुहरू दैनिक आधारमा धार्मिक समारोहहरूमा भाग लिन्छन्, धेरै हिन्दुहरूले आफ्नो घरमा धार्मिक समारोहहरू पनि राख्छन्। हिन्दुहरूले निम्न दैनिक अनुष्ठानहरू गर्छन्: * [[पूजा]] * विभिन्न शास्त्रहरूको संयुक्त पठन। * [[कीर्तन]] र [[भजन]]: प्रार्थना, मन्त्र र धार्मिक गीत गाउने अनुष्ठान हो। * विभिन्न प्रकारका [[ध्यान]], जस्तै [[जप]]-[[माला]] मालामा [[मन्त्र]] पठन, जाप भनिने अनुष्ठान === चाडपर्वहरू === {{मुख्य|हिन्दु चाडपर्वहरूको सूची}} [[चित्र:Holi Festival of Colors Utah, United States 2013.jpg|thumb|[[संयुक्त राज्य अमेरिका]]को उटाहस्थित श्री श्री राधाकृष्ण मन्दिरमा [[होली]] मनाइँदै।]] [[हिन्दु चाडपर्वहरूको सूची|हिन्दु चाडपर्वहरू]] ([[संस्कृत]]: उत्सव) व्यक्तिगत र सामाजिक जीवनलाई धर्ममा जोड्ने समारोहहरू हुन्। केही प्रमुख क्षेत्रीय वा अखिल हिन्दु चाडपर्वहरू समावेश छन्: {{div col|colwidth=18em}} * [[माघे सङ्क्रान्ति]] * [[वसन्त पञ्चमी]] * [[महाशिवरात्रि]] * [[होली]] * [[राम नवमी]] * [[कात्तिक पूर्णिमा]] * [[साउन शुक्ल पूर्णिमा|रक्षा बन्धन]] * [[कृष्ण जन्माष्टमी]] * [[गणेश चतुर्थी]] * [[नौरथा|नवरात्रि]] * [[विजयादसमी]] * [[दसैँ]] * [[दुर्गा पूजा]] * [[लक्ष्मी पूजा]] * [[दीपावली]] * [[तिहार]] * [[भाइटीका]] * [[छठ]] {{div col end}} == तीर्थयात्रा == {{मुख्य|तीर्थ|परिक्रम}} [[चित्र:Ahilya Ghat by the Ganges, Varanasi.jpg|thumb|[[बनारस]] हिन्दु धर्मको सबैभन्दा पवित्र शहरहरू मध्ये एक हो।]] तीर्थयात्रा हिन्दु धर्मको विशेषता मध्ये एक धार्मिक अभ्यास हो। तीर्थस्थललाई "तीर्थ" वा "धाम" भनिन्छ। हिन्दु धर्ममा सबैभन्दा लोकप्रिय तीर्थहरू [[इलाहाबाद]], [[हरिद्वार]] र [[बनारस]] हुन्, र वैष्णव धर्ममा पनि [[वृन्दावन]] हुन्। अन्य महत्त्वपूर्ण तीर्थस्थलहरू तिनीहरूका प्राचीन मन्दिरहरूको लागि प्रसिद्ध: * [[पुरी]] * [[बद्रीनाथ मन्दिर]] * [[केदारनाथ मन्दिर]] * [[गङ्गोत्री]] * [[यमुनोत्री]] == हिन्दु समाज == === आश्रमहरू === {{मुख्य|आश्रम}}परम्परागत रूपमा हिन्दु धर्ममा, जीवनलाई चार आश्रम (अवधि वा चरणहरू) मा विभाजित गरिएको छ। * [[ब्रह्मचर्य]] जीवनको पहिलो अवधि हो, प्रशिक्षणको चरण जुन विद्यार्थीले भिक्षुको रूपमा बिताउँछ, यौन परित्याग गर्ने र गुरुको सेवामा संलग्न हुने, उहाँबाट आध्यात्मिक ज्ञान प्राप्त गर्ने। * [[आश्रम व्यवस्था|गृहस्थ]] पारिवारिक जीवन, काम। यस आश्रममा काम र अर्थको पुरुषार्थ गरिन्छ। हिन्दु परिवारको पुरुषको कर्तव्य भनेको आफ्ना आमाबाबु, बच्चाहरू, पाहुनाहरू र सन्त व्यक्तिहरूलाई समर्थन गर्नु हो। * [[वानप्रस्थ]] भनेको संन्यास र भौतिक संसारको पूर्ण त्यागको तयारी हो। यस चरणमा, सबै भौतिक जिम्मेवारीहरू क्रमशः वयस्क बच्चाहरूलाई हस्तान्तरण गरिन्छ र अधिक समय आध्यात्मिक अभ्यासहरू र पवित्र स्थानहरूमा तीर्थयात्राहरूमा समर्पित हुन्छ। * [[सन्न्यास]] जीवनको अन्तिम चरण हो, भौतिक संसारको पूर्ण त्यागको चरण, जसको विशेषता तपस्या र आत्म-चेतना र आध्यात्मिक अभ्यासहरूमा पूर्ण समर्पण हुन्छ। यस आश्रममा मृत्युको क्षण र मोक्ष प्राप्तिको लागि आवश्यक तयारी गरिन्छ। === भिक्षुवाद === {{मुख्य|सन्न्यास|साधु}} [[चित्र:Baba in Kathmandu.jpg|thumb|[[पशुपतिनाथ मन्दिर]]मा [[साधु]]]] केही हिन्दुहरूले मुक्ति वा आध्यात्मिक पूर्णताको कुनै अन्य रूप प्राप्त गर्नमा ध्यान केन्द्रित गर्ने लक्ष्यका साथ "संन्यास" को भिक्षु जीवन शैली रोज्छन्। भिक्षुहरूले आफूलाई सरल र तपस्वी जीवनमा समर्पित गर्छन्, ब्रह्मचर्यको व्रत लिन्छन् र सबै भौतिक गतिविधिहरू रोक्छन्, पूर्णतया आध्यात्मिक अभ्यासहरूमा ध्यान केन्द्रित गर्छन्, जसको उद्देश्य ईश्वरको प्राप्ति हो। === वर्ण र जाति व्यवस्था === {{मुख्य|हिन्दु वर्ण व्यवस्था}}हिन्दु धर्ममा, समाजलाई परम्परागत रूपमा चार वर्गमा विभाजन गरिएको छ, जसलाई वर्ण भनिन्छ, जसको अर्थ संस्कृतमा "रङ, आकार, रूप" हो। * [[ब्राह्मण]] - शिक्षक र पुजारी * [[क्षत्रिय]] - योद्धा, शासक, कुलीन * [[वैश्य]] - किसान, व्यापारी र उद्यमी * [[शूद्र]] - सेवक र कामदार == जनसङ्ख्या == {{मुख्य|हिन्दु बसोबास भएका देशहरू}} [[चित्र:Countries by percentage of adherents to Hinduism.svg|thumb|देश अनुसार हिन्दुहरूको प्रतिशत|center|700px]] [[नेपाल]], [[भारत]], र [[मौरिसस|मौरिसस्]] का राज्यहरू लगायत [[इन्डोनेसिया|इन्डोनेशिया]]को बाली टापुमा मुख्य जनसङ्ख्या हिन्दु छन्। केही मात्रामा यी देशहरूमा पनि हिन्दुहरू छन्: सबैभन्दा धेरै हिन्दुहरूको अनुपात भएका देशहरू: # {{flag|नेपाल}}{{Spaced en dash}}८१.३%<ref>{{Cite web|url=http://cbs.gov.np/wp-content/uploads/2012/11/National%20Report.pdf|title=2011 Nepal Census Report|year=2012|archive-url=https://web.archive.org/web/20130525062716/http://cbs.gov.np/wp-content/uploads/2012/11/National%20Report.pdf|archive-date=25 May 2013}} {{Webarchive|url=https://web.archive.org/web/20130418041642/http://cbs.gov.np/wp-content/uploads/2012/11/National%20Report.pdf |date=18 April 2013 }}</ref> # {{flag|भारत}}{{Spaced en dash}}७९.८%<ref>{{Cite web|url=https://www.livepopulation.com/country/india.html|title=Population of India Today|website=livepopulation.com|archive-url=https://web.archive.org/web/20190403015935/https://www.livepopulation.com/country/india.html|archive-date=3 April 2019|access-date=5 August 2018|url-status=live}}</ref> # {{flag|मौरिसस}}{{Spaced en dash}}४८.५%<ref>{{Cite web|url=http://www.gov.mu/portal/goc/cso/file/2011VolIIPC.pdf|title=Resident population by religion and sex|publisher=[[Statistics Mauritius]]|page=68|archive-url=https://web.archive.org/web/20131016141533/http://www.gov.mu/portal/goc/cso/file/2011VolIIPC.pdf|archive-date=16 October 2013|access-date=1 November 2012}}</ref> # {{flag|गयाना}}{{Spaced en dash}}२८.४%<ref>{{Cite web|url=https://www.cia.gov/the-world-factbook/countries/guyana/|title=The World Factbook|access-date=10 May 2011}} {{Webarchive|url=https://web.archive.org/web/20210107032754/https://www.cia.gov/the-world-factbook/countries/guyana/ |date=7 January 2021 }}</ref> # {{flag|फिजी}}{{Spaced en dash}}२७.९%<ref>{{Cite web|url=https://www.cia.gov/the-world-factbook/countries/fiji/|title=The World Factbook|access-date=10 May 2011}} {{Webarchive|url=https://web.archive.org/web/20210827055140/https://www.cia.gov/the |date=27 August 2021 }}</ref> # {{flag|भुटान}}{{Spaced en dash}}२२.६%<ref>{{Cite web|url=https://www.state.gov/g/drl/rls/irf/2009/127364.htm|title=Bhutan|website=U.S. Department of State|archive-url=https://web.archive.org/web/20091130031858/http://www.state.gov/g/drl/rls/irf/2009/127364.htm|archive-date=30 November 2009}}</ref> # {{flag|सुरिनाम}}{{Spaced en dash}}२२.३%<ref>{{Cite web|url=https://www.state.gov/g/drl/rls/irf/2009/127405.htm|title=Suriname|website=U.S. Department of State|archive-url=https://web.archive.org/web/20091130031911/http://www.state.gov/g/drl/rls/irf/2009/127405.htm|archive-date=30 November 2009}}</ref> # {{flag|ट्रिनिडाड र टोबागो}}{{Spaced en dash}}१८.२%<ref>{{Cite web|url=https://guardian.co.tt/sites/default/files/story/2011_DemographicReport.pdf|title=2011 Demographic Report|page=18|archive-url=https://web.archive.org/web/20171019211618/https://guardian.co.tt/sites/default/files/story/2011_DemographicReport.pdf|archive-date=19 October 2017}} {{Webarchive|url=https://web.archive.org/web/20171019211618/https://guardian.co.tt/sites/default/files/story/2011_DemographicReport.pdf |date=19 October 2017 }}</ref> # {{flag|कतार}}{{Spaced en dash}}१३.८%<ref>{{Cite journal|last1=Robin|first1=Christian Julien|last2=Gorea|first2=Maria|date=2002|title=Les vestiges antiques de la grotte de Hôq (Suqutra, Yémen) (note d'information)|url=https://www.persee.fr/doc/crai_0065-0536_2002_num_146_2_22441|journal=Comptes rendus des séances de l'Académie des Inscriptions et Belles-Lettres|volume=146|issue=2|pages=409–445|doi=10.3406/crai.2002.22441 | issn = 0065-0536 }}</ref> # {{flag|श्रीलङ्का}}{{Spaced en dash}}१२.६%<ref>{{Cite web|url=http://www.statistics.gov.lk/PopHouSat/CPH2011/index.php?fileName=pop43&gp=Activities&tpl=3|title=The Census of Population and Housing of Sri Lanka-2011|year=2011|website=Department of Census and Statistics|archive-url=https://web.archive.org/web/20181224211239/http://www.statistics.gov.lk/PopHouSat/CPH2011/index.php?fileName=pop43&gp=Activities&tpl=3|archive-date=24 December 2018|access-date=29 July 2013|url-status=live}} {{Webarchive|url=https://web.archive.org/web/20190107065148/http://www.statistics.gov.lk/PopHouSat/CPH2011/index.php?fileName=pop43&gp=Activities&tpl=3 |date=7 January 2019 }}</ref> # {{flag|बहराइन}}{{Spaced en dash}}९.८% # {{flag|बङ्गलादेश}}{{Spaced en dash}}८.५%<ref>{{Cite web|url=http://www.bbs.gov.bd/WebTestApplication/userfiles/Image/SVRS/SVRS-10.pdf|title=SVRS 2010|publisher=Bangladesh Bureau of Statistics|page=176 (Table P–14)|archive-url=https://web.archive.org/web/20121113153533/http://www.bbs.gov.bd/WebTestApplication/userfiles/Image/SVRS/SVRS-10.pdf|archive-date=13 November 2012|access-date=2 September 2012}} {{Webarchive|url=https://web.archive.org/web/20121113153533/http://www.bbs.gov.bd/WebTestApplication/userfiles/Image/SVRS/SVRS-10.pdf |date=13 November 2012 }}</ref> # [[रियुनियन]] {{spaced en dash}}६.८% # {{flag|संयुक्त अरब इमिरेट्स| the}}{{Spaced en dash}}६.६%<ref>{{Cite web|url=https://2009-2017.state.gov/j/drl/rls/irf/2007/90223.htm|title=United Arab Emirates|website=U.S. Department of State}}</ref> # {{flag|मलेसिया}}{{Spaced en dash}}६.३%.<ref name="cia.gov">{{Cite web|url=https://www.cia.gov/the-world-factbook/countries/malaysia/|title=The World Factbook|access-date=10 May 2011}} {{Webarchive|url=https://archive.today/20211108232943/https://www.cia.gov/the-world-factbook/countries/malaysia/ |date=8 November 2021 }}</ref> # {{flag|कुवेत}}{{Spaced en dash}}६%<ref>{{Cite web|url=http://www.globalreligiousfutures.org/|title=Pew-Templeton: Global Religious Futures Project|website=www.globalreligiousfutures.org|access-date=18 March 2021}} {{Webarchive|url=https://web.archive.org/web/20130503083508/http://www.globalreligiousfutures.org/ |date=3 May 2013 }}</ref> # {{flag|ओमान}}{{Spaced en dash}}५.५%<ref>{{cite web|url=https://www.cia.gov/the-world-factbook/countries/oman/|title=Middle East OMAN|date=22 September 2021|publisher=CIA The World Factbook}} {{Webarchive|url=https://web.archive.org/web/20210313050143/https://www.cia.gov/the-world-factbook/countries/oman/ |date=13 March 2021 }}</ref> # {{flag|सिङ्गापुर}}{{Spaced en dash}}५%<ref name="2010 census Full report">{{Cite web|url=http://www.singstat.gov.sg/pubn/popn/C2010sr1/cop2010sr1.pdf|title=Census of population 2010: Statistical Release 1 on Demographic Characteristics, Education, Language and Religion|last=Singapore Department of Statistics|date=12 January 2011|archive-url=https://web.archive.org/web/20110303155259/http://www.singstat.gov.sg/pubn/popn/C2010sr1/cop2010sr1.pdf|archive-date=3 March 2011|access-date=16 January 2011}} {{Webarchive|url=https://web.archive.org/web/20110303155259/http://www.singstat.gov.sg/pubn/popn/C2010sr1/cop2010sr1.pdf |date=3 March 2011 }}</ref> # {{flag|इन्डोनेसिया}}{{Spaced en dash}}३.८६%<ref>{{cite web|url=https://2009-2017.state.gov/j/drl/rls/irf/2010_5/168356.htm|title=Indonesia: Religious Freedoms Report 2010|date=2011|publisher=[[US State Department]]|access-date=4 March 2021}}</ref> # {{flag|न्युजिल्यान्ड}}{{Spaced en dash}}२.६२%<ref>{{Cite web|url=https://www.stats.govt.nz/assets/Uploads/2018-Census-totals-by-topic/Download-data/2018-census-totals-by-topic-national-highlights.xlsx|title=Table 26, 2018 Census Data – Tables|format=xlsx|archive-url=https://web.archive.org/web/20200413185957/https://www.stats.govt.nz/assets/Uploads/2018-Census-totals-by-topic/Download-data/2018-census-totals-by-topic-national-highlights.xlsx|archive-date=13 April 2020|access-date=29 December 2020|url-status=live}}</ref> # {{flag|सेसेल्स}}{{Spaced en dash}}२.४%<ref>{{Cite web|url=https://www.cia.gov/the-world-factbook/countries/seychelles/|title=The World Factbook|access-date=10 May 2011}} {{Webarchive|url=https://web.archive.org/web/20210128072600/https://www.cia.gov/the-world-factbook/countries/seychelles/ |date=28 January 2021 }}</ref> # {{flag|पाकिस्तान}}{{Spaced en dash}}२.१४%<ref>{{Cite web|url=http://www.census.gov.pk/Religion.htm|title=Population by religion in Pakistan|archive-url=https://web.archive.org/web/20140402081116/http://www.census.gov.pk/Religion.htm|archive-date=2 April 2014|access-date=3 March 2021}} {{Webarchive|url=https://web.archive.org/web/20140402081116/http://www.census.gov.pk/Religion.htm |date=2 April 2014 }}</ref> {| class="wikitable sortable" style="margin: 1em auto;" |+महाद्वीप अनुसार हिन्दु धर्म (२०१७-१८) !महादेशहरू ! scope="col" |हिन्दु जनसङ्ख्या ! scope="col" |हिन्दु जनसङ्ख्याको % ! scope="col" |महाद्वीप जनसङ्ख्याको % ! scope="col" |अनुयायी गतिशीलता ! scope="col" |विश्व गतिशीलता |- | align="center" |[[एसिया]] | align="center" |१,०७४,७२८,९०१ | align="center" |९९.२६६ | align="center" |२६.०१ | align="center" |{{increase}} बढ्दै | align="center" |{{increase}} बढ्दै |- | align="center" |[[युरोप]] | align="center" |२,०३०,९०४ | align="center" |०.२१४ | align="center" |०.२७८ | align="center" |{{increase}} बढ्दै | align="center" |{{increase}} बढ्दै |- | align="center" |[[महाअमेरिका]] | align="center" |२,८०६,३४४ | align="center" |०.२६३ | align="center" |०.२८१ | align="center" |{{increase}} बढ्दै | align="center" |{{increase}} बढ्दै |- | align="center" |[[अफ्रिका]] | align="center" |२,०१३,७०५ | align="center" |०.२१३ | align="center" |०.२२५ | align="center" |{{increase}} बढ्दै | align="center" |{{increase}} बढ्दै |- | align="center" |[[ओसिनिया]] | align="center" |७९१,६१५ | align="center" |०.०७१ | align="center" |२.०५३ | align="center" |{{increase}} बढ्दै | align="center" |{{increase}} बढ्दै |- !सञ्चित !१,०८२,३७१ ,४६९ !१०० !१५.०३ !{{increase}} बढ्दै !{{increase}} बढ्दै |} प्रबल हिन्दु समुदाय पूर्व-सोभियत सङ्घका राष्ट्रहरू, विषेशगरि [[रुस]], र [[पोल्यान्ड|पोल्यान्ड]]मा पनि छन्। [[इन्डोनेसिया|इन्डोनेशिया]]का टापुहरू जाभा, सुलावेसी, सुमात्रा र बोर्निओमा पनि प्रसस्त रैथाने हिन्दुहरू छन्। हिन्दुत्व [[योग]]को रूपमा त झनै विश्वब्यापि रूपमा फैलिएको छ। संयुक्त राज्य अमेरिकामा मात्रै ३ करोड [[योग]]का अनुयायीहरू छन्। == सतावट == हिन्दुहरूले ऐतिहासिक धार्मिक सतावट, निरन्तर धार्मिक उत्पीडन र व्यवस्थित हिंसा दुवैको अनुभव गरेका छन्। यी जबरजस्ती धर्म परिवर्तन, दस्तावेजी [[नरसंहार]], [[मन्दिर]] भत्काउने र अपवित्रको रूपमा हुन्छन्। हिन्दुहरूको ऐतिहासिक सतावट [[मुसलमान|मुस्लिम]] शासकहरू र [[इसाई धर्म|क्रिश्चियन]] मिसनरीहरूद्वारा पनि भयो। [[मुगल साम्राज्य|मुगल काल]]मा हिन्दुहरूलाई जिज्या तिर्न बाध्य पारिएको थियो। [[भारतको विभाजन]]को समयमा मुस्लिम र हिन्दुहरू सहित २००,००० देखि दस लाख मानिसहरू मारिएका थिए। आधुनिक समयमा, हिन्दुहरूले भेदभावको सामना गर्नुपरेको थियो। विश्वका धेरै भागहरूमा र धेरै देशहरूमा विशेष गरी [[पाकिस्तान]], [[बङ्गलादेश]], [[फिजी]] र अन्यमा उत्पीडन र जबरजस्ती धर्म परिवर्तनको सामना गर्नुपरेको छ।<ref>{{Cite book|last=Brass|first=Paul R.|url=https://books.google.com/books?id=9XGZ0kKmJx0C&q=persecution+of+hindus+by+muslims|title=The Production of Hindu-Muslim Violence in Contemporary India|date=1 May 2011|publisher=University of Washington Press|isbn=978-0-295-80060-8|language=en|author-link=Paul R. Brass}}</ref><ref name=":1">{{Cite book|last=Jain|first=Meenakshi|title=Flight of deities and rebirth of temples: espisodes from Indian history|date=2019|isbn=978-81-7305-619-2|location=New Delhi|oclc=1091630081}}</ref> ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} {{Portal bar|हिन्दु धर्म|}} {{हिन्दु धर्म}} rd90qtwux8wy7nipy5ev605o3xmtz2k 1361161 1361157 2026-06-11T12:46:51Z NDG 73687 [[Special:Contributions/RANGAVANTHIYAR|RANGAVANTHIYAR]] ([[User talk:RANGAVANTHIYAR|वार्तालाप]])द्वारा [[User:InternetArchiveBot|InternetArchiveBot]]द्वारा गरिएको पछिल्लो संशोधनतर्फ उल्टाइएका सम्पादनहरू 1345864 wikitext text/x-wiki {{हिन्दु धर्म बाकस}} '''हिन्दु धर्म''' एक [[धर्म]] हो, जसलाई प्रायः धार्मिक परम्पराहरू र [[दार्शनिक विद्यालय]]हरूको सङ्ग्रहको रूपमा वर्णन गरिएको छ जुन [[भारतीय उपमहाद्वीप]]मा उत्पत्ति भएको हो। [[संस्कृत]]मा हिन्दु धर्मको ऐतिहासिक नाम '''सनातन धर्म''' हो जसको अर्थ "शाश्वत धर्म", "अनन्त मार्ग" वा "अनन्त कानून" हो। हिन्दु धर्मको जरा [[वैदिक सभ्यता|वैदिक]], [[सिन्धु घाटीको सभ्यता|सिन्धु घाटी]] र [[द्रविड]] सभ्यताहरूमा छ, त्यसैले हिन्दु धर्मलाई [[पृथ्वी|संसार]]को सबैभन्दा पुरानो धर्म भनिन्छ। [[धर्मशास्त्र|धर्म]], [[कर्म]], [[संसार (बौद्ध)|संसार]], [[माया (हिन्दु धर्म)|माया]], [[मोक्ष]] र [[योग]] जस्ता धार्मिक पदहरूले गर्दा हिन्दु धर्मलाई विशिष्ट मानिन्छ। हिन्दु धर्ममा ठुलो सङ्ख्यामा [[धर्मशास्त्र|शास्त्र]]हरू छन्, जुन दुई मुख्य कोटीहरूमा पर्छन्: [[श्रुति]] र [[स्मृति]]। महत्वपूर्ण हिन्दु ग्रन्थहरू [[वेद]], [[उपनिषद्]], [[पुराण]], [[रामायण]], [[महाभारत]], [[श्रीमद्भगवद गीता]] र [[आगम]]हरू हुन्। हिन्दु धर्म १ अर्ब ५० करोड भन्दा बढी मानिसहरू द्वारा अभ्यास गरिएको छ - हिन्दु धर्म संसारमा तेस्रो ठुलो धर्म हो। [[भारत]] र [[नेपाल]]को [[जनसङ्ख्या]]को अधिकांश हिस्सा हिन्दुहरू छन्। जस मध्ये ९६% [[दक्षिण एसिया]]मा छन्। [[बङ्गलादेश]], [[श्रीलङ्का]], [[पाकिस्तान]], [[इन्डोनेसिया]], [[मलेसिया]], [[सिङ्गापुर]], [[मौरिसस]], [[फिजी]], [[सुरिनाम]], [[गयाना]], [[ट्रिनिडाड र टोबागो]], [[संयुक्त अधिराज्य]], [[क्यानडा]] र [[संयुक्त राज्य अमेरिका]] जस्ता देशहरूमा हिन्दु धर्मका अनुयायीहरूको उल्लेखनीय सङ्ख्या पाइन्छ। == नाम == {{Further|हिन्दुहरू}} हिन्दु शब्द [[हिन्द-आर्य भाषाहरू|हिन्द-आर्य]]/[[संस्कृत]] मूल सिन्धुबाट आएको हो, जसलाई [[भारतीय उपमहाद्वीप]]को [[उत्तर-पश्चिम प्रदेश|उत्तरपश्चिमी]] भागमा रहेको [[सिन्धु नदी]]को नाम मानिन्छ।<ref>{{Cite web|url=https://pahilopost.com/content/-6839.html|title=हिन्दु कि सनातन वैदिक धर्म?|last=जोशी|first=सत्यराज|date=३१ साउन २०७२|website=पहिलो पोस्ट|accessdate=१५ मङ्सिर २०७९}}</ref><ref>{{Cite web|url=https://nagariknews.nagariknetwork.com/opinion/114394-1483935480.html|title=‘हिन्दु’को परिचय|last=शर्मा|first=डा तारानाथ|date=२५ पुस २०७३|website=नागरीक|language=ne|accessdate=१५ मङ्सिर २०७९}}</ref> [[संस्कृत]]मा, सनातन धर्मले लगभग "अनन्त [[कानून]]" वा कम शाब्दिक रूपमा, "अनन्त मार्ग" लाई अनुवाद गरिन्छ। [[पाली भाषा]]मा, समकक्ष शब्द ''धम्मो सनातनो'' हो।<ref name="harvey20012">so {{cite book|author=Harvey, Andrew|title=Teachings of the Hindu Mystics|publisher=Shambhala|location=Boulder|year=2001|pages=xiii|isbn=1-57062-449-6}}). See also [[René Guénon]], ''Introduction to the Study of the Hindu Doctrines'' (1921 ed.), Sophia Perennis, ISBN 0-900588-74-8, part III, chapter 5 "The Law of Manu", p. 146. On the meaning of the word "Dharma", see also [[René Guénon]], ''Studies in Hinduism'', Sophia Perennis, ISBN 0-900588-69-3, chapter 5, p. 45</ref> [[नेपाली भाषा]]मा, संस्कृत [[तत्सम]] ''धर्म'' शब्द लाई (यसको संस्कृत अर्थ "कानून" वा अधिक शाब्दिक रूपमा "जुन समर्थन गर्दछ; के दृढतापूर्वक स्थापित छ") "[[धर्म]]" (निष्ठा) को रूपमा प्रयोग गरिन्छ।<ref name="harvey2001">so {{cite book|author=Harvey, Andrew|title=Teachings of the Hindu Mystics|publisher=Shambhala|location=Boulder|year=2001|pages=xiii|isbn=1-57062-449-6}}). See also [[René Guénon]], ''Introduction to the Study of the Hindu Doctrines'' (1921 ed.), Sophia Perennis, ISBN 0-900588-74-8, part III, chapter 5 "The Law of Manu", p. 146. On the meaning of the word "Dharma", see also [[René Guénon]], ''Studies in Hinduism'', Sophia Perennis, ISBN 0-900588-69-3, chapter 5, p. 45</ref> == परिभाषा == [[चित्र:Aum Om navy blue circle coral.svg|thumb|हिन्दु धर्ममा [[ૐ]] लाई धार्मिक प्रतीकको रूपमा प्रयोग गरिन्छ]] हिन्दु धर्म शब्दले ढाकेको परम्परा र विचारहरूको व्यापक दायराको कारण, एक व्यापक परिभाषामा पुग्न गाह्रो छ।<ref name=":0">{{Cite web|url=https://nepalpatra.com/religion-culture/90312/|title=हिन्दु कसलाई भन्ने?|website=नेपालपत्र|accessdate=2022-12-01}}{{Dead link|date=March 2026 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> हिन्दु धर्मले [[अध्यात्म]] र [[परम्परा]]हरूमा विचारहरूको विविधता समावेश गर्दछ, तर कुनै चर्चको आदेश छैन, कुनै निर्विवाद धार्मिक अधिकारीहरू छैनन्, कुनै शासक निकाय छैन, कुनै अगमवक्ता(हरू) वा कुनै एक पवित्र पुस्तकहरू छैनन्; हिन्दुहरूले बहुदेववादी, सर्वधर्मवादी, सर्वधर्मवादी, पाण्डेइस्टिक, हेनोथेस्टिक, एकेश्वरवादी, अद्वैतवादी, [[अज्ञेयवाद|अज्ञेयवादी]], [[नास्तिक]] वा [[मानवता|मानवतावादी]] हुन रोज्न सक्छन्।<ref>MK Gandhi, ''[http://www.mkgandhi.org/ebks/essence_of_hinduism.pdf The Essence of Hinduism] {{Webarchive|url=https://web.archive.org/web/20150724045756/http://www.mkgandhi.org/ebks/essence_of_hinduism.pdf|date=24 July 2015}}'', Editor: VB Kher, Navajivan Publishing"</ref><ref>{{Cite book|title=Encyclopedia of Violence, Peace and Conflict|publisher=Academic Press|year=2008|isbn=978-0-12-369503-1|editor-last=Kurtz|editor-first=Lester}}</ref> हिन्दु धर्मलाई धर्म, धार्मिक परम्परा, धार्मिक विश्वासको एक सेट, र "जीवन पद्धति" को रूपमा विभिन्न रूपमा परिभाषित गरिएको छ।<ref name=":0" /> === प्रकारहरू === * हिन्दु धर्मको सबैभन्दा पुरानो रूप लोक विश्वास हो, जुन स्थानीय [[देवता]]हरूको [[पूजा]] र देवता रूपहरू द्वारा विशेषता हो। * [[वैदिक सभ्यता|वैदिक]]: वैदिक शास्त्रहरूमा आधारित, जसमध्ये सबैभन्दा महत्त्वपूर्ण र प्राचीन [[ऋग्वेद]] मानिन्छ। * [[वेदान्त|वेदान्तिक]]: [[उपनिषद्|उपनिषद]]हरूमा आधारित छ - चार [[वेद]]हरूसँगै धार्मिक र दार्शनिक ग्रंथहरू। * [[योग]]: योगको दिशालाई [[पतञ्जलि]]को योग सूत्रमा प्रस्तुत * [[भक्ति]] ([[भगवान]]को मायालु भक्ति सेवा): हिन्दु धर्ममा भक्तिको मुख्य [[वैष्णव]] परम्परा हो यस अवधारणाको ढाँचा भित्र पहिचान गरिएका अन्य समूहहरूमा एकदम अन्तर्निहित छ। === सम्प्रदाय === {{Further|सम्प्रदाय}} हिन्दु धर्ममा कुनै पनि सामान्य, केन्द्रीय सिद्धान्त छैन जुन सबै हिन्दु परम्पराहरूको लागि आधिकारिक हो, र धेरै हिन्दुहरूले आफूलाई कुनै पनि विशेष परम्परासँग सम्बन्धित ठान्दैनन्। तथापि, विद्वानहरूले आधुनिक हिन्दु धर्ममा चार मुख्य दिशाहरू छुट्याएका छन्:<ref name="junemcdaniel6">June McDaniel "Hinduism", in {{Cite book|last=Corrigan|first=John|title=The Oxford Handbook of Religion and Emotion|publisher=Oxford University Press|year=2007|isbn=978-0-19-517021-4|pages=52–53}}</ref><ref>{{Cite web|url=https://www.eadarsha.com/nep/article/%e0%a4%b9%e0%a4%bf%e0%a4%a8%e0%a5%8d%e0%a4%a6%e0%a5%82-%e0%a4%a7%e0%a4%b0%e0%a5%8d%e0%a4%ae-%e0%a4%b0-%e0%a4%af%e0%a4%b8%e0%a4%95%e0%a4%be-%e0%a4%b8%e0%a4%ae%e0%a5%8d%e0%a4%aa%e0%a5%8d%e0%a4%b0/|title=हिन्दु धर्म र यसका सम्प्रदायहरू|last=|first=|website=आदर्श समाज|accessdate=2022-12-01}}{{Dead link|date=April 2025 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> * [[शैव|शैव (]][[शिव]]) * [[वैष्णव|वैष्णव (]][[विष्णु]]) * शाक्त ([[देवी]]) * [[स्मार्त]] (पाँच देवतालाई समान) हिन्दु धर्मले असंख्य दिव्य प्राणीहरूलाई पनि स्वीकार गर्दछ, धेरै हिन्दुहरूले [[देवता]]हरूलाई एकल अवैयक्तिक निरपेक्ष वा परम वास्तविकता वा [[ईश्वर]]को रूप वा रूपहरू मान्छन, जबकि केही [[हिन्दुहरू]]ले एक विशिष्ट देवताले सर्वोच्चलाई प्रतिनिधित्व गर्दछ र विभिन्न देवताहरू यस सर्वोच्चको निम्न अभिव्यक्तिहरू हुन् भनी विश्वास गरिन्छ।<ref>{{Cite web|url=https://www.newsofnepal.com/2020/06/15/326065/|title=के हो धार्मिक सम्प्रदाय ?|website=नेपाल समाचारपत्र|language=|accessdate=2022-12-01}}</ref> == विश्वासहरू == हिन्दु विश्वासका प्रमुख विषयवस्तुहरूमा धर्म (नैतिकता/कर्तव्यहरू), संसार (आकांक्षाहरू र परिणामस्वरूप जन्म, जीवन, मृत्यु र [[पुनर्जन्म (बौद्ध धर्म)|पुनर्जन्म]]), [[कर्म]] (कार्य, अभिप्राय, र परिणामहरू) समावेश छन् (तर यसमा सीमित छैनन्), [[मोक्ष]] (लग्न र संसारबाट मुक्ति), र विभिन्न योगहरू (मार्ग वा अभ्यासहरू)। === पुरुषार्थ === {{Further|पुरुषार्थ}} [[चित्र:Reincarnation AS.jpg|thumb|पुनर्जन्मको प्रतिनिधित्व]] * '''[[धर्म]]''': हिन्दु धर्ममा [[धर्म]]लाई मानवको प्रमुख लक्ष्य मानिन्छ। धर्मको अवधारणाले [[जीवन]] र [[ब्रह्माण्ड]]लाई सम्भव बनाउने क्रम, र कर्तव्य, [[अधिकार]], [[कानून]], आचरण, सद्गुण र "जीवनको सही तरिका" समावेश गर्ने व्यवहारहरू समावेश गर्दछ। * [[अर्थशास्त्र (ग्रन्थ)|'''अर्थ''']]: अर्थ भनेको जीविकोपार्जन, दायित्व र आर्थिक समृद्धिका लागि धनको वस्तुगत र सद्गुणको खोज हो। यो [[राजनीति|राजनीतिक]] जीवन, [[कूटनीति]], र भौतिक कल्याण समावेशी छ। अर्थ अवधारणामा सबै "जीवनका साधनहरू", गतिविधिहरू र स्रोतहरू समावेश छन् जसले व्यक्तिलाई राज्यमा हुन सक्षम बनाउँछ, [[धन]], क्यारियर र वित्तीय सुरक्षा। * [[कामसूत्र|'''काम''']]: काम भनेको चाहना, इच्छा, जोश, लालसा, इन्द्रियको आनन्द, जीवनको सौन्दर्यपूर्ण आनन्द, स्नेह, वा [[प्रेम]], [[यौन]] अर्थ सहित वा बिना। * '''[[मोक्ष]]''': मोक्ष हिन्दु धर्ममा परम, सबैभन्दा महत्त्वपूर्ण लक्ष्य हो। एक अर्थमा, मोक्ष [[दुख|दुःख]], कष्ट र संसार (जन्म-पुनर्जन्म चक्र) बाट मुक्तिसँग सम्बन्धित अवधारणा हो। यस एस्केटोलोजिकल चक्रबाट मुक्ति, जीवन पछि, विशेष गरी हिन्दु धर्मका [[ईश्वर]]वादी विद्यालयहरूमा मोक्ष भनिन्छ। * '''[[कर्म]]''': कर्मले शाब्दिक रूपमा कार्य, काम, वा कर्मको रूपमा अनुवाद गर्दछ, र "कारण र प्रभावको नैतिक कानून" को [[वैदिक सभ्यता|वैदिक]] सिद्धान्तलाई पनि जनाउँछ। यो [[जन्म]], [[जीवन]], [[अन्तिम संस्कार|मृत्यु]] र [[पुनर्जन्म (बौद्ध धर्म)|पुनर्जन्म]]को चक्रलाई [[संसार (बौद्ध)|संसार]] भनिन्छ। मोक्षको माध्यमबाट संसारबाट [[मुक्ति]]ले दिगो सुख र [[शान्ति]] सुनिश्चित गर्ने विश्वास गरिन्छ। === योग === {{Further|योग|राजयोग|श्रीमद्भगवद गीता|पतञ्जलि योगसूत्र}} [[चित्र:Shiva Bangalore.jpg|thumb|योग [[ध्यान]]मा भगवान [[शिव]]को मूर्ति]] हिन्दुका लागि जीवनको अन्तिम लक्ष्य जेसुकै होस्, यो लक्ष्य प्राप्त गर्नका लागि [[ऋषि]]हरूले दिएका धेरै [[योग]] विधिहरू छन्। विभिन्न प्रकारका योगको वर्णन गर्ने आधारभूत ग्रन्थहरूमा [[श्रीमद्भगवद गीता]], [[पतञ्जलि योगसूत्र|योग सूत्र]], हठयोग प्रदीपिका र [[उपनिषद्|उपनिषद]]हरू समावेश छन्। योगका मुख्य प्रकारहरू, जसलाई अनुसरण गरेर उच्चतम आध्यात्मिक पूर्णता (मोक्ष वा समाधि) प्राप्त गर्न सम्भव छ: * [[भक्ति योग|'''भक्ति योग''']]: प्रेम र भक्ति मार्ग * '''[[कर्म योग]]''': सही कार्यको बाटो * '''[[राज योग]]''': ध्यान को मार्ग * '''[[ज्ञान योग]]''': ज्ञान वा बुद्धिको मार्ग === ईश्वरको अवधारणा === {{Further|हिन्दु धर्ममा ईश्वर|अवतार|देवी-देवता}} धेरै हिन्दुहरूले [[ब्रह्माण्ड]]को सृष्टि गर्ने, कायम राख्ने र नष्ट गर्ने ईश्वरीय वास्तविकतालाई स्वीकार गर्छन्, तर केही हिन्दु सम्प्रदायहरूले यो विचारलाई अस्वीकार गर्छन्। धेरैजसो हिन्दुहरू एक विश्वव्यापी [[ईश्वर]]मा विश्वास गर्छन् जो एकै साथ प्रत्येक जीवित [[प्राणी]] भित्र छ र जसलाई विभिन्न तरिकामा सम्पर्क गर्न सकिन्छ। [[पुराण]] र हिन्दु महाकाव्यहरू "[[महाभारत]]" र "[[रामायण]]"ले [[समाज]]मा धर्मको पुनर्स्थापना गर्न र मानवतालाई [[मोक्ष]] (जन्म र मृत्युको चक्रबाट मुक्ति) तर्फ लैजानको लागि कसरी देवताहरू मानव रूपमा [[पृथ्वी]]मा अवतरण गर्छन् भन्ने बारे धेरै कथाहरू वर्णन गर्दछ। यस्ता [[देवता]]का अवतारहरूलाई "[[अवतार]]" भनिन्छ। [[विष्णु]]का सबैभन्दा महत्त्वपूर्ण अवतारहरू (जसलाई [[वैष्णव]] अधिकांश अनुयायीहरूले ईश्वरको मूल रूप मान्छन्) [[कृष्ण]] र [[श्रीराम अवतार|राम]] हुन्। हिन्दु धर्मको अधिकांश वैष्णव परम्पराहरूमा, कृष्णलाई विष्णुको सबैभन्दा पूर्ण अवतार मानिन्छ, जसमा व्यक्तिगत निरपेक्षताका सबै दिव्य गुणहरू प्रकट हुन्छन्। [[गौडिय वैष्णव सम्प्रदाय|गौडिया वैष्णववाद]], पुष्टिमार्ग र निम्बार्क सम्प्रदाय जस्ता वैष्णववादका प्रवाहहरूमा, कृष्णलाई स्वयं-भगवानको रूपमा [[पूजा]] गरिन्छ। === आध्यात्मिक साधनाको अन्तिम लक्ष्य === आध्यात्मिक साधनाको अन्तिम लक्ष्यलाई "[[मोक्ष]]", "[[निर्वाण]]" वा "[[समाधि|समाधी]]" जस्ता शब्दहरूद्वारा जनाइएको छ, र हिन्दु धर्मका विभिन्न दिशाहरूलाई विभिन्न तरिकाले बुझिन्छ: * भगवान संग एकता को जागरूकता * [[ईश्वर|परमेश्वर]]सँगको अनन्त सम्बन्धको जागरूकता र उहाँको [[वैकुण्ठ|निवासमा]] फर्कन * परमेश्वरको शुद्ध प्रेमको उपलब्धिहरू * सबैको एकताको चेतना * आफ्नो साँचो आत्म महसुस गर्दै * पूर्ण शान्ति प्राप्त गर्दै * भौतिक इच्छाहरूबाट पूर्ण स्वतन्त्रता === स्वर्ग र नरकको अवधारणा === {{Further|लोक|त्रैलोक्य}} हिन्दु धर्मको [[पुराण]] साहित्यमा [[नरक]] र [[स्वर्ग]]को अवधारणा प्रस्तुत गरिएको छ। यसले अनगिन्ती स्वर्गीय र नरकीय लोकहरू ([[ग्रह]] वा अस्तित्वको विमानहरू) को [[वर्ण|वर्णन]] गर्दछ, जहाँ मृतकहरूलाई उनीहरूले गरेका राम्रो वा पापपूर्ण कामहरूको आधारमा पुरस्कृत वा सजाय दिइन्छ। आत्माको नरकीय सूक्ष्म क्षेत्रहरूमा झरेको [[आत्मा (हिन्दु धर्म)|आत्मा]]लाई खाना र पानीको बलिदानद्वारा त्यहाँबाट उद्धार गर्न सकिन्छ, जुन अन्तिम [[अवतार]]मा यसका छोराछोरी र नातिनातिनाहरूले गर्नु पर्छ। स्वर्गीय वा नरकीय ग्रहहरूमा निश्चित समय बिताएपछि, आत्मा विभिन्न भौतिक तत्वहरू ([[पृथ्वी]], [[पानी|जल]], [[हावा|वायु]], [[आगो|अग्नि]], ईथर र अन्य सूक्ष्म तत्वहरू) मार्फत जान्छ र अन्तमा, ८,४००,००० प्रकारका [[शरीर]]हरू मध्ये एकमा [[पुनर्जन्म (बौद्ध धर्म)|पुनर्जन्म]] हुन्छ। == इतिहास == {{Main page|हिन्दु धर्मको इतिहास}}हिन्दु धर्मको इतिहास [[फलाम युग]] देखि [[भारतीय उपमहाद्वीप]]मा धर्मको विकाससँग मेल खान्छ, यसका केही परम्पराहरू कांस्य युग [[सिन्धु घाटीको सभ्यता]] जस्ता प्रागैतिहासिक धर्महरूमा फर्किएका छन्। यसरी यसलाई संसारको "सबैभन्दा पुरानो धर्म" भनिन्छ। यसमा एक अज्ञात मातृदेवीको मूर्ति, [[शिव]] [[पशुपतिनाथ मन्दिर|पशुपति]] आदी जस्तो देवताहरूको मुद्राहरू, लिंग, पीपलको पूजा, इत्यादि प्रमुख छन्।विद्वानहरूले हिन्दु धर्मलाई विभिन्न [[भारतीय संस्कृति]] र परम्पराहरूको संश्लेषणको रूपमा मान्दछन्, जसमा विभिन्न जराहरू छन् र कुनै एकल संस्थापक छैन।[[चित्र:Kailash Tibet edited.jpg|thumb|[[तिब्बत]]को पवित्र [[कैलाश पर्वत]]लाई [[शिव]]को आध्यात्मिक निवास मानिन्छ]] == पवित्र ग्रन्थहरू == {{Main article|हिन्दु धर्मग्रन्थ|हिन्दु दर्शन}} शताब्दीयौंदेखि, हिन्दु धर्मका पवित्र शास्त्रहरू पद्य रूपमा मौखिक रूपमा प्रसारित गरिएको थियो, जुन स्मरणको सुविधाको लागि प्रयोग गरिएको थियो। [[ऋषि]]हरूले [[शिक्षा]]हरूलाई सिद्ध गरेका छन् र [[धर्मशास्त्र]]को क्यानन विस्तार गरेका छन्। उत्तर-[[वैदिक सभ्यता|वैदिक]] र आधुनिक हिन्दु धर्मका केही परम्पराहरूमा, शास्त्रहरूलाई शाब्दिक रूपमा व्याख्या गरिएको छैन - तिनीहरूमा निहित नैतिक र रूपक अर्थलाई बढी महत्त्व दिइन्छ। अधिकांश पवित्र ग्रन्थहरू संस्कृतमा लेखिएका छन्। उनीहरूलाई [[श्रुति]] र [[स्मृति]] गरी दुई वर्गमा विभाजन गरिएको छ। === श्रुति === {{Main article|श्रुति}} [[चित्र:Rigveda MS2097.jpg|200px|thumb|[[ऋग्वेद]], संसारको सबैभन्दा पुरानो धार्मिक ग्रन्थहरू मध्ये एक।]] "श्रुति" चार [[वेद]]हरूको सम्बन्धमा प्रयोग गरिन्छ, जुन हिन्दु धर्मको सबैभन्दा पुरानो पवित्र ग्रन्थ मानिन्छ। धेरैजसो हिन्दुहरूले वेदहरूलाई मानिसद्वारा सृष्टि नगरिएको, अनन्त ईश्वरीय रूपमा प्रकट गरिएका शास्त्रहरू जुन पवित्र ऋषिहरूको मध्यस्थता मार्फत मानवजातिलाई दिइएको थियो भनेर सम्मान गर्छन्। धेरै हिन्दुहरूले विश्वास गर्छन् कि वेदहरूमा उल्लिखित आध्यात्मिक सत्यहरू अनन्त छन्, [[इतिहास]]भरि उनीहरूलाई नयाँ रूपहरूमा व्यक्त गरिएको छ र विभिन्न तरिकामा व्याख्या गरिएको छ। श्रुतिमा चार वेदहरू छन्: [[ऋग्वेद]], [[सामवेद]], [[यजुर्वेद]], [[अथर्ववेद]]। प्रत्येक वेद चार भागमा विभाजित छ: [[संहितापाठ|संहिता]], [[ब्राह्मणम्]], [[आरण्यक]] र [[उपनिषद्]]। === स्मृति === {{Main article|स्मृति}} [[चित्र:Krishna Arjuna Gita.jpg|thumb|left|भगवान [[कृष्ण]]ले [[अर्जुन]]लाई [[श्रीमद्भगवद गीता]] भन्नुहुन्छ]] स्मृतिहरूमध्ये सबैभन्दा महत्त्वपूर्ण महाकाव्य [[महाभारत]] र [[रामायण]] हुन्। [[श्रीमद्भगवद गीता]] महाभारतको अंश हो र हिन्दु धर्मका सबै पवित्र ग्रन्थहरूमा सबैभन्दा व्यापक रूपमा ज्ञात र अध्ययन गरिएको मानिन्छ। यसमा [[कुरुक्षेत्र युद्ध|कुरुक्षेत्रको महान युद्ध]] सुरु हुनु अघि योद्धा राजकुमार [[अर्जुन]]लाई [[कृष्ण]]को दार्शनिक निर्देशनहरू छन्। दुबै हिन्दुहरू र धेरै पश्चिमी [[वैज्ञानिक]]हरू र दार्शनिकहरूले श्रीमद्भगवद गीतामा सबै वेदहरूको मुख्य सार समावेश गर्दछ भन्ने विश्वास गर्छन्। स्मृति वर्गमा [[पुराण]]हरू पनि समावेश छन्, जसले हिन्दु विश्वास र [[दर्शन]]लाई सजिलो र पहुँचयोग्य रूपमा प्रस्तुत गर्दछ, र धेरै फरक कथाहरू समावेश गर्दछ। त्यहाँ छुट्टै [[धर्मशास्त्र|शास्त्र]]हरू पनि छन् जुन हिन्दु धर्ममा केही निर्देशनहरू मात्र पछ्याइएको छ, जसमा [[देवीमाहात्म्य]], [[तन्त्र]], [[पतञ्जलि योगसूत्र|योग सूत्र]], [[शिवसूत्र]]हरू र [[आगम]]हरू समावेश छन्। साथै एक महत्त्वपूर्ण पाठ [[मनुस्मृति]] हो, जसले वर्णाश्रमका कानून र सामाजिक मान्यताहरू वर्णन गर्दछ। == अभ्यासहरू == === मन्दिर र मूर्ति === {{मुख्य|मन्दिर|मूर्ति}}हिन्दु धर्ममा [[देवता]]हरूको [[मूर्ति]]द्वारा पूजा गरिन्छ। मूर्तिको मुख्य भूमिका देवतासँग गहिरो व्यक्तिगत सम्बन्ध बनाउनु हो। मूर्तिलाई देवताको रूप मानिन्छ, उहाँभन्दा भिन्न छैन। देवताको एक गुण सर्वव्यापी भएकोले मानिसलाई आफ्नो आराधना गर्न सजिलो होस् भनेर देवता पनि मूर्तिको माध्यमबाट प्रकट हुन्छन्। [[पद्म पुराण]]मा, विशेष गरी, यो भनिएको छ कि मूर्तिलाई साधारण ढुङ्गा वा काठको टुक्रा सम्झनु हुँदैन - मूर्ति [[भगवान]]को प्रत्यक्ष रूप हो। === शुभ प्रतिक === {{मुख्य|ओम|स्वस्तिक|टीका}} [[चित्र:Three basic Hindu symbols.jpg|thumb|हिन्दु प्रतीकहरू]] हिन्दु धर्ममा प्रत्येक प्रतीकको यसको पवित्र अर्थ हुन्छ। अक्षर "[[ૐ]] (ओम)" (जसले [[ब्रह्म|परब्रह्म]]को प्रतीक हो) र [[स्वस्तिक]]को चिह्न (कल्याणको प्रतिनिधित्व गर्ने) सबै हिन्दु धर्मको पवित्र प्रतीक मान्न सकिन्छ। जबकि, उदाहरणका लागि, [[टीका|तिलक]]का विभिन्न रूपहरूले विभिन्न हिन्दु सम्प्रदायका अनुयायीहरूलाई पहिचान गर्न मद्दत गर्दछ। त्यहाँ धेरै प्रतीकहरू छन् जुन निश्चित देवताहरूसँग चिनिन्छन्; यसमा [[कमल]], [[चक्र]] र [[वीणा]] समावेश छन्। === संस्कार === धेरै हिन्दुहरू दैनिक आधारमा धार्मिक समारोहहरूमा भाग लिन्छन्, धेरै हिन्दुहरूले आफ्नो घरमा धार्मिक समारोहहरू पनि राख्छन्। हिन्दुहरूले निम्न दैनिक अनुष्ठानहरू गर्छन्: * [[पूजा]] * विभिन्न शास्त्रहरूको संयुक्त पठन। * [[कीर्तन]] र [[भजन]]: प्रार्थना, मन्त्र र धार्मिक गीत गाउने अनुष्ठान हो। * विभिन्न प्रकारका [[ध्यान]], जस्तै [[जप]]-[[माला]] मालामा [[मन्त्र]] पठन, जाप भनिने अनुष्ठान === चाडपर्वहरू === {{मुख्य|हिन्दु चाडपर्वहरूको सूची}} [[चित्र:Holi Festival of Colors Utah, United States 2013.jpg|thumb|[[संयुक्त राज्य अमेरिका]]को उटाहस्थित श्री श्री राधाकृष्ण मन्दिरमा [[होली]] मनाइँदै।]] [[हिन्दु चाडपर्वहरूको सूची|हिन्दु चाडपर्वहरू]] ([[संस्कृत]]: उत्सव) व्यक्तिगत र सामाजिक जीवनलाई धर्ममा जोड्ने समारोहहरू हुन्। केही प्रमुख क्षेत्रीय वा अखिल हिन्दु चाडपर्वहरू समावेश छन्: {{div col|colwidth=18em}} * [[माघे सङ्क्रान्ति]] * [[वसन्त पञ्चमी]] * [[महाशिवरात्रि]] * [[होली]] * [[राम नवमी]] * [[कात्तिक पूर्णिमा]] * [[साउन शुक्ल पूर्णिमा|रक्षा बन्धन]] * [[कृष्ण जन्माष्टमी]] * [[गणेश चतुर्थी]] * [[नौरथा|नवरात्रि]] * [[विजयादसमी]] * [[दसैँ]] * [[दुर्गा पूजा]] * [[लक्ष्मी पूजा]] * [[दीपावली]] * [[तिहार]] * [[भाइटीका]] * [[छठ]] {{div col end}} == तीर्थयात्रा == {{मुख्य|तीर्थ|परिक्रम}} [[चित्र:Ahilya Ghat by the Ganges, Varanasi.jpg|thumb|[[बनारस]] हिन्दु धर्मको सबैभन्दा पवित्र शहरहरू मध्ये एक हो।]] तीर्थयात्रा हिन्दु धर्मको विशेषता मध्ये एक धार्मिक अभ्यास हो। तीर्थस्थललाई "तीर्थ" वा "धाम" भनिन्छ। हिन्दु धर्ममा सबैभन्दा लोकप्रिय तीर्थहरू [[इलाहाबाद]], [[हरिद्वार]] र [[बनारस]] हुन्, र वैष्णव धर्ममा पनि [[वृन्दावन]] हुन्। अन्य महत्त्वपूर्ण तीर्थस्थलहरू तिनीहरूका प्राचीन मन्दिरहरूको लागि प्रसिद्ध: * [[पुरी]] * [[बद्रीनाथ मन्दिर]] * [[केदारनाथ मन्दिर]] * [[गङ्गोत्री]] * [[यमुनोत्री]] == हिन्दु समाज == === आश्रमहरू === {{मुख्य|आश्रम}}परम्परागत रूपमा हिन्दु धर्ममा, जीवनलाई चार आश्रम (अवधि वा चरणहरू) मा विभाजित गरिएको छ। * [[ब्रह्मचर्य]] जीवनको पहिलो अवधि हो, प्रशिक्षणको चरण जुन विद्यार्थीले भिक्षुको रूपमा बिताउँछ, यौन परित्याग गर्ने र गुरुको सेवामा संलग्न हुने, उहाँबाट आध्यात्मिक ज्ञान प्राप्त गर्ने। * [[आश्रम व्यवस्था|गृहस्थ]] पारिवारिक जीवन, काम। यस आश्रममा काम र अर्थको पुरुषार्थ गरिन्छ। हिन्दु परिवारको पुरुषको कर्तव्य भनेको आफ्ना आमाबाबु, बच्चाहरू, पाहुनाहरू र सन्त व्यक्तिहरूलाई समर्थन गर्नु हो। * [[वानप्रस्थ]] भनेको संन्यास र भौतिक संसारको पूर्ण त्यागको तयारी हो। यस चरणमा, सबै भौतिक जिम्मेवारीहरू क्रमशः वयस्क बच्चाहरूलाई हस्तान्तरण गरिन्छ र अधिक समय आध्यात्मिक अभ्यासहरू र पवित्र स्थानहरूमा तीर्थयात्राहरूमा समर्पित हुन्छ। * [[सन्न्यास]] जीवनको अन्तिम चरण हो, भौतिक संसारको पूर्ण त्यागको चरण, जसको विशेषता तपस्या र आत्म-चेतना र आध्यात्मिक अभ्यासहरूमा पूर्ण समर्पण हुन्छ। यस आश्रममा मृत्युको क्षण र मोक्ष प्राप्तिको लागि आवश्यक तयारी गरिन्छ। === भिक्षुवाद === {{मुख्य|सन्न्यास|साधु}} [[चित्र:Baba in Kathmandu.jpg|thumb|[[पशुपतिनाथ मन्दिर]]मा [[साधु]]]] केही हिन्दुहरूले मुक्ति वा आध्यात्मिक पूर्णताको कुनै अन्य रूप प्राप्त गर्नमा ध्यान केन्द्रित गर्ने लक्ष्यका साथ "संन्यास" को भिक्षु जीवन शैली रोज्छन्। भिक्षुहरूले आफूलाई सरल र तपस्वी जीवनमा समर्पित गर्छन्, ब्रह्मचर्यको व्रत लिन्छन् र सबै भौतिक गतिविधिहरू रोक्छन्, पूर्णतया आध्यात्मिक अभ्यासहरूमा ध्यान केन्द्रित गर्छन्, जसको उद्देश्य ईश्वरको प्राप्ति हो। === वर्ण र जाति व्यवस्था === {{मुख्य|हिन्दु वर्ण व्यवस्था}}हिन्दु धर्ममा, समाजलाई परम्परागत रूपमा चार वर्गमा विभाजन गरिएको छ, जसलाई वर्ण भनिन्छ, जसको अर्थ संस्कृतमा "रङ, आकार, रूप" हो। * [[ब्राह्मण]] - शिक्षक र पुजारी * [[क्षत्रिय]] - योद्धा, शासक, कुलीन * [[वैश्य]] - किसान, व्यापारी र उद्यमी * [[शूद्र]] - सेवक र कामदार == जनसङ्ख्या == {{मुख्य|हिन्दु बसोबास भएका देशहरू}} [[चित्र:Countries by percentage of adherents to Hinduism.svg|thumb|देश अनुसार हिन्दुहरूको प्रतिशत|center|700px]] [[नेपाल]], [[भारत]], र [[मौरिसस|मौरिसस्]] का राज्यहरू लगायत [[इन्डोनेसिया|इन्डोनेशिया]]को बाली टापुमा मुख्य जनसङ्ख्या हिन्दु छन्। केही मात्रामा यी देशहरूमा पनि हिन्दुहरू छन्: सबैभन्दा धेरै हिन्दुहरूको अनुपात भएका देशहरू: # {{flag|नेपाल}}{{Spaced en dash}}८१.३%<ref>{{Cite web|url=http://cbs.gov.np/wp-content/uploads/2012/11/National%20Report.pdf|title=2011 Nepal Census Report|year=2012|archive-url=https://web.archive.org/web/20130525062716/http://cbs.gov.np/wp-content/uploads/2012/11/National%20Report.pdf|archive-date=25 May 2013}} {{Webarchive|url=https://web.archive.org/web/20130418041642/http://cbs.gov.np/wp-content/uploads/2012/11/National%20Report.pdf |date=18 April 2013 }}</ref> # {{flag|भारत}}{{Spaced en dash}}७९.८%<ref>{{Cite web|url=https://www.livepopulation.com/country/india.html|title=Population of India Today|website=livepopulation.com|archive-url=https://web.archive.org/web/20190403015935/https://www.livepopulation.com/country/india.html|archive-date=3 April 2019|access-date=5 August 2018|url-status=live}}</ref> # {{flag|मौरिसस}}{{Spaced en dash}}४८.५%<ref>{{Cite web|url=http://www.gov.mu/portal/goc/cso/file/2011VolIIPC.pdf|title=Resident population by religion and sex|publisher=[[Statistics Mauritius]]|page=68|archive-url=https://web.archive.org/web/20131016141533/http://www.gov.mu/portal/goc/cso/file/2011VolIIPC.pdf|archive-date=16 October 2013|access-date=1 November 2012}}</ref> # {{flag|गयाना}}{{Spaced en dash}}२८.४%<ref>{{Cite web|url=https://www.cia.gov/the-world-factbook/countries/guyana/|title=The World Factbook|access-date=10 May 2011}} {{Webarchive|url=https://web.archive.org/web/20210107032754/https://www.cia.gov/the-world-factbook/countries/guyana/ |date=7 January 2021 }}</ref> # {{flag|फिजी}}{{Spaced en dash}}२७.९%<ref>{{Cite web|url=https://www.cia.gov/the-world-factbook/countries/fiji/|title=The World Factbook|access-date=10 May 2011}} {{Webarchive|url=https://web.archive.org/web/20210827055140/https://www.cia.gov/the |date=27 August 2021 }}</ref> # {{flag|भुटान}}{{Spaced en dash}}२२.६%<ref>{{Cite web|url=https://www.state.gov/g/drl/rls/irf/2009/127364.htm|title=Bhutan|website=U.S. Department of State|archive-url=https://web.archive.org/web/20091130031858/http://www.state.gov/g/drl/rls/irf/2009/127364.htm|archive-date=30 November 2009}}</ref> # {{flag|सुरिनाम}}{{Spaced en dash}}२२.३%<ref>{{Cite web|url=https://www.state.gov/g/drl/rls/irf/2009/127405.htm|title=Suriname|website=U.S. Department of State|archive-url=https://web.archive.org/web/20091130031911/http://www.state.gov/g/drl/rls/irf/2009/127405.htm|archive-date=30 November 2009}}</ref> # {{flag|ट्रिनिडाड र टोबागो}}{{Spaced en dash}}१८.२%<ref>{{Cite web|url=https://guardian.co.tt/sites/default/files/story/2011_DemographicReport.pdf|title=2011 Demographic Report|page=18|archive-url=https://web.archive.org/web/20171019211618/https://guardian.co.tt/sites/default/files/story/2011_DemographicReport.pdf|archive-date=19 October 2017}} {{Webarchive|url=https://web.archive.org/web/20171019211618/https://guardian.co.tt/sites/default/files/story/2011_DemographicReport.pdf |date=19 October 2017 }}</ref> # {{flag|कतार}}{{Spaced en dash}}१३.८%<ref>{{Cite journal|last1=Robin|first1=Christian Julien|last2=Gorea|first2=Maria|date=2002|title=Les vestiges antiques de la grotte de Hôq (Suqutra, Yémen) (note d'information)|url=https://www.persee.fr/doc/crai_0065-0536_2002_num_146_2_22441|journal=Comptes rendus des séances de l'Académie des Inscriptions et Belles-Lettres|volume=146|issue=2|pages=409–445|doi=10.3406/crai.2002.22441 | issn = 0065-0536 }}</ref> # {{flag|श्रीलङ्का}}{{Spaced en dash}}१२.६%<ref>{{Cite web|url=http://www.statistics.gov.lk/PopHouSat/CPH2011/index.php?fileName=pop43&gp=Activities&tpl=3|title=The Census of Population and Housing of Sri Lanka-2011|year=2011|website=Department of Census and Statistics|archive-url=https://web.archive.org/web/20181224211239/http://www.statistics.gov.lk/PopHouSat/CPH2011/index.php?fileName=pop43&gp=Activities&tpl=3|archive-date=24 December 2018|access-date=29 July 2013|url-status=live}} {{Webarchive|url=https://web.archive.org/web/20190107065148/http://www.statistics.gov.lk/PopHouSat/CPH2011/index.php?fileName=pop43&gp=Activities&tpl=3 |date=7 January 2019 }}</ref> # {{flag|बहराइन}}{{Spaced en dash}}९.८% # {{flag|बङ्गलादेश}}{{Spaced en dash}}८.५%<ref>{{Cite web|url=http://www.bbs.gov.bd/WebTestApplication/userfiles/Image/SVRS/SVRS-10.pdf|title=SVRS 2010|publisher=Bangladesh Bureau of Statistics|page=176 (Table P–14)|archive-url=https://web.archive.org/web/20121113153533/http://www.bbs.gov.bd/WebTestApplication/userfiles/Image/SVRS/SVRS-10.pdf|archive-date=13 November 2012|access-date=2 September 2012}} {{Webarchive|url=https://web.archive.org/web/20121113153533/http://www.bbs.gov.bd/WebTestApplication/userfiles/Image/SVRS/SVRS-10.pdf |date=13 November 2012 }}</ref> # [[रियुनियन]] {{spaced en dash}}६.८% # {{flag|संयुक्त अरब इमिरेट्स| the}}{{Spaced en dash}}६.६%<ref>{{Cite web|url=https://2009-2017.state.gov/j/drl/rls/irf/2007/90223.htm|title=United Arab Emirates|website=U.S. Department of State}}</ref> # {{flag|मलेसिया}}{{Spaced en dash}}६.३%.<ref name="cia.gov">{{Cite web|url=https://www.cia.gov/the-world-factbook/countries/malaysia/|title=The World Factbook|access-date=10 May 2011}} {{Webarchive|url=https://archive.today/20211108232943/https://www.cia.gov/the-world-factbook/countries/malaysia/ |date=8 November 2021 }}</ref> # {{flag|कुवेत}}{{Spaced en dash}}६%<ref>{{Cite web|url=http://www.globalreligiousfutures.org/|title=Pew-Templeton: Global Religious Futures Project|website=www.globalreligiousfutures.org|access-date=18 March 2021}} {{Webarchive|url=https://web.archive.org/web/20130503083508/http://www.globalreligiousfutures.org/ |date=3 May 2013 }}</ref> # {{flag|ओमान}}{{Spaced en dash}}५.५%<ref>{{cite web|url=https://www.cia.gov/the-world-factbook/countries/oman/|title=Middle East OMAN|date=22 September 2021|publisher=CIA The World Factbook}} {{Webarchive|url=https://web.archive.org/web/20210313050143/https://www.cia.gov/the-world-factbook/countries/oman/ |date=13 March 2021 }}</ref> # {{flag|सिङ्गापुर}}{{Spaced en dash}}५%<ref name="2010 census Full report">{{Cite web|url=http://www.singstat.gov.sg/pubn/popn/C2010sr1/cop2010sr1.pdf|title=Census of population 2010: Statistical Release 1 on Demographic Characteristics, Education, Language and Religion|last=Singapore Department of Statistics|date=12 January 2011|archive-url=https://web.archive.org/web/20110303155259/http://www.singstat.gov.sg/pubn/popn/C2010sr1/cop2010sr1.pdf|archive-date=3 March 2011|access-date=16 January 2011}} {{Webarchive|url=https://web.archive.org/web/20110303155259/http://www.singstat.gov.sg/pubn/popn/C2010sr1/cop2010sr1.pdf |date=3 March 2011 }}</ref> # {{flag|इन्डोनेसिया}}{{Spaced en dash}}३.८६%<ref>{{cite web|url=https://2009-2017.state.gov/j/drl/rls/irf/2010_5/168356.htm|title=Indonesia: Religious Freedoms Report 2010|date=2011|publisher=[[US State Department]]|access-date=4 March 2021}}</ref> # {{flag|न्युजिल्यान्ड}}{{Spaced en dash}}२.६२%<ref>{{Cite web|url=https://www.stats.govt.nz/assets/Uploads/2018-Census-totals-by-topic/Download-data/2018-census-totals-by-topic-national-highlights.xlsx|title=Table 26, 2018 Census Data – Tables|format=xlsx|archive-url=https://web.archive.org/web/20200413185957/https://www.stats.govt.nz/assets/Uploads/2018-Census-totals-by-topic/Download-data/2018-census-totals-by-topic-national-highlights.xlsx|archive-date=13 April 2020|access-date=29 December 2020|url-status=live}}</ref> # {{flag|सेसेल्स}}{{Spaced en dash}}२.४%<ref>{{Cite web|url=https://www.cia.gov/the-world-factbook/countries/seychelles/|title=The World Factbook|access-date=10 May 2011}} {{Webarchive|url=https://web.archive.org/web/20210128072600/https://www.cia.gov/the-world-factbook/countries/seychelles/ |date=28 January 2021 }}</ref> # {{flag|पाकिस्तान}}{{Spaced en dash}}२.१४%<ref>{{Cite web|url=http://www.census.gov.pk/Religion.htm|title=Population by religion in Pakistan|archive-url=https://web.archive.org/web/20140402081116/http://www.census.gov.pk/Religion.htm|archive-date=2 April 2014|access-date=3 March 2021}} {{Webarchive|url=https://web.archive.org/web/20140402081116/http://www.census.gov.pk/Religion.htm |date=2 April 2014 }}</ref> {| class="wikitable sortable" style="margin: 1em auto;" |+महाद्वीप अनुसार हिन्दु धर्म (२०१७-१८) !महादेशहरू ! scope="col" |हिन्दु जनसङ्ख्या ! scope="col" |हिन्दु जनसङ्ख्याको % ! scope="col" |महाद्वीप जनसङ्ख्याको % ! scope="col" |अनुयायी गतिशीलता ! scope="col" |विश्व गतिशीलता |- | align="center" |[[एसिया]] | align="center" |१,०७४,७२८,९०१ | align="center" |९९.२६६ | align="center" |२६.०१ | align="center" |{{increase}} बढ्दै | align="center" |{{increase}} बढ्दै |- | align="center" |[[युरोप]] | align="center" |२,०३०,९०४ | align="center" |०.२१४ | align="center" |०.२७८ | align="center" |{{increase}} बढ्दै | align="center" |{{increase}} बढ्दै |- | align="center" |[[महाअमेरिका]] | align="center" |२,८०६,३४४ | align="center" |०.२६३ | align="center" |०.२८१ | align="center" |{{increase}} बढ्दै | align="center" |{{increase}} बढ्दै |- | align="center" |[[अफ्रिका]] | align="center" |२,०१३,७०५ | align="center" |०.२१३ | align="center" |०.२२५ | align="center" |{{increase}} बढ्दै | align="center" |{{increase}} बढ्दै |- | align="center" |[[ओसिनिया]] | align="center" |७९१,६१५ | align="center" |०.०७१ | align="center" |२.०५३ | align="center" |{{increase}} बढ्दै | align="center" |{{increase}} बढ्दै |- !सञ्चित !१,०८२,३७१ ,४६९ !१०० !१५.०३ !{{increase}} बढ्दै !{{increase}} बढ्दै |} प्रबल हिन्दु समुदाय पूर्व-सोभियत सङ्घका राष्ट्रहरू, विषेशगरि [[रुस]], र [[पोल्यान्ड|पोल्यान्ड]]मा पनि छन्। [[इन्डोनेसिया|इन्डोनेशिया]]का टापुहरू जाभा, सुलावेसी, सुमात्रा र बोर्निओमा पनि प्रसस्त रैथाने हिन्दुहरू छन्। हिन्दुत्व [[योग]]को रूपमा त झनै विश्वब्यापि रूपमा फैलिएको छ। संयुक्त राज्य अमेरिकामा मात्रै ३ करोड [[योग]]का अनुयायीहरू छन्। == सतावट == हिन्दुहरूले ऐतिहासिक धार्मिक सतावट, निरन्तर धार्मिक उत्पीडन र व्यवस्थित हिंसा दुवैको अनुभव गरेका छन्। यी जबरजस्ती धर्म परिवर्तन, दस्तावेजी [[नरसंहार]], [[मन्दिर]] भत्काउने र अपवित्रको रूपमा हुन्छन्। हिन्दुहरूको ऐतिहासिक सतावट [[मुसलमान|मुस्लिम]] शासकहरू र [[इसाई धर्म|क्रिश्चियन]] मिसनरीहरूद्वारा पनि भयो। [[मुगल साम्राज्य|मुगल काल]]मा हिन्दुहरूलाई जिज्या तिर्न बाध्य पारिएको थियो। [[भारतको विभाजन]]को समयमा मुस्लिम र हिन्दुहरू सहित २००,००० देखि दस लाख मानिसहरू मारिएका थिए। आधुनिक समयमा, हिन्दुहरूले भेदभावको सामना गर्नुपरेको थियो। विश्वका धेरै भागहरूमा र धेरै देशहरूमा विशेष गरी [[पाकिस्तान]], [[बङ्गलादेश]], [[फिजी]] र अन्यमा उत्पीडन र जबरजस्ती धर्म परिवर्तनको सामना गर्नुपरेको छ।<ref>{{Cite book|last=Brass|first=Paul R.|url=https://books.google.com/books?id=9XGZ0kKmJx0C&q=persecution+of+hindus+by+muslims|title=The Production of Hindu-Muslim Violence in Contemporary India|date=1 May 2011|publisher=University of Washington Press|isbn=978-0-295-80060-8|language=en|author-link=Paul R. Brass}}</ref><ref name=":1">{{Cite book|last=Jain|first=Meenakshi|title=Flight of deities and rebirth of temples: espisodes from Indian history|date=2019|isbn=978-81-7305-619-2|location=New Delhi|oclc=1091630081}}</ref> ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} {{Portal bar|हिन्दु धर्म|}} {{हिन्दु धर्म}} 6ffpup8aojm73fpbp76656e42ceklgi लक्ष्मीप्रसाद देवकोटा 0 3223 1361473 1356422 2026-06-12T10:36:14Z Bishaldev100 28807 /* */ 1361473 wikitext text/x-wiki {{विशेष लेख}} {{संक्षिप्त विवरण|नेपाली लेखक}} {{Infobox officeholder | name = लक्ष्मीप्रसाद देवकोटा | honorific_prefix = महाकवि | image = Laxmi Prasad Devkota 3.jpg | caption = लक्ष्मीप्रसाद देवकोटा | alt = | country = [[नेपाल]] | office = [[शिक्षा, विज्ञान तथा प्रविधि मन्त्रालय (नेपाल)|शिक्षा विज्ञान तथा प्रविधि मन्त्री]] | term_start = २०१४ साउन ११ | term_end = २०१५ जेठ २ | primeminister = [[कुँवर इन्द्रजीत सिंह|कुँवर इन्द्रजित सिंह]] | predecessor = | successor = | signature = | birth_date = १९६६ कार्तिक २७ | birth_place = धोविधारा, [[काठमाडौँ]], [[नेपाल अधिराज्य|नेपाल]] | death_date = २०१६ भाद्र २९ | death_place = [[आर्यघाट]] | nationality = [[नेपाली]] | notableworks = | parents = तिलमाधव देवकोटा (पिता)<br>अमरराज्य लक्ष्मी देवी (आमा) | spouse = मानदेवी चालिसे | children = ५ छोरी <br> ४ छोरा | relatives = लोकप्रिया देवी (दिदी) | occupation = साहित्यकार र विद्वान् | image_size = 200px | period = | native_name = | native_name_lang = ne | monarch = [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]] }} '''लक्ष्मीप्रसाद देवकोटा''' एक नेपाली कवि तथा साहित्यकार हुन् । उनको जन्म वि. सं. १९६६ कार्तिक २७ गते '[[लक्ष्मी पूजा|लक्ष्मीपुजा]]'को दिनमा [[काठमाडौँ]]को डिल्लीबजारमा भएको थियो।<ref>{{वेब स्रोत|लेखक=|शीर्षक=लक्ष्मीप्रसाद देवकोटा / परिचय|युआरएल=http://kavitakosh.org/kk/%E0%A4%B2%E0%A4%95%E0%A5%8D%E0%A4%B7%E0%A5%8D%E0%A4%AE%E0%A5%80%E0%A4%AA%E0%A5%8D%E0%A4%B0%E0%A4%B8%E0%A4%BE%E0%A4%A6_%E0%A4%A6%E0%A5%87%E0%A4%B5%E0%A4%95%E0%A5%8B%E0%A4%9F%E0%A4%BE_/_%E0%A4%AA%E0%A4%B0%E0%A4%BF%E0%A4%9A%E0%A4%AF|कार्य=|प्रकाशक=|वेबसाइट=कविताकोश|भाषा=नेपाली)|अभिलेखमिति=|अभिलेखयुआरएल=|मिति=|पहुँचमिति=२० अप्रिल २०२२}}</ref> उनी [[नेपाल|नेपाली]] [[साहित्य]]का [[महाकवि]]का रूपमा सुप्रसिद्ध छन्।<ref>{{वेब स्रोत|लेखक=|शीर्षक=को हुन् लक्ष्मीप्रसाद ? महाकवि देवकोटाको जीवनी|युआरएल=https://lokpati.com/2018/11/5165/|कार्य=|प्रकाशक=लोकपाटी|वेबसाइट=|भाषा=नेपाली)|अभिलेखमिति=|अभिलेखयुआरएल=|मिति=|पहुँचमिति=२० अप्रिल २०२२}}</ref> देवकोटा नेपाली साहित्यका कविता, आख्यान, नाटक र निबन्ध गरी साहित्यका चारवटै विधामा कलम चलाउने बहुमुखी प्रतिभाका धनी मानिन्छन्। उनले [[कविता]] र [[निबन्ध]] विधामा गरेका योगदानहरू उच्च कोटिको मानिन्छ। उनले [[मुनामदन]], [[सुलोचना (महाकाव्य)|सुलोचना]], [[शाकुन्तल (महाकाव्य)|शाकुन्तल]]जस्ता अद्वितीय कृतिहरू लेखेका छन्। विशेष गरी [[मुनामदन]] कृतिका लागि उनी सबैभन्दा प्रख्यात छन्।<ref>{{वेब स्रोत|लेखक=|शीर्षक=मुना र मदनको बिछोडको प्रेम कहानी|युआरएल=https://everestdainik.com/2017/08/106798/?amp_markup=1|कार्य=|प्रकाशक=|वेबसाइट=एभरेष्ट दैनिक|भाषा=नेपाली)|अभिलेखमिति=|अभिलेखयुआरएल=|मिति=|पहुँचमिति=२० अप्रिल २०२२}}</ref><ref>{{वेब स्रोत|लेखक=कृष्णप्रसाद कोइराला |शीर्षक=समीक्षा-मुनामदन खण्डकाव्य|युआरएल=https://sahityasangraha.com/2017/07/28/%E0%A4%AE%E0%A5%81%E0%A4%A8%E0%A4%BE%E0%A4%AE%E0%A4%A6%E0%A4%A8-%E0%A4%96%E0%A4%A3%E0%A5%8D%E0%A4%A1%E0%A4%95%E0%A4%BE%E0%A4%B5%E0%A5%8D%E0%A4%AF/|कार्य=|प्रकाशक=|वेबसाइट=|भाषा=नेपाली)|अभिलेखमिति=|अभिलेखयुआरएल=|मिति=|पहुँचमिति=२० अप्रिल २०२२}}</ref> उनको निधन वि.सं. २०१६ भाद्र २९ मा पचास वर्षकै उमेरमा नै भएको थियो। == प्रारम्भिक जीवन र शिक्षा == देवकोटा पण्डित तीलमाधव र अमर राज्यलक्ष्मी देवीका तेस्रो छोरा थिए। उनी डिल्लीबजार, धोबीधारा, [[काठमाडौँ]]मा [[तिहार]]को [[लक्ष्मी पूजा]]का दिन जन्मिएका थिए। विक्रम सम्वत् १९६६ साल कार्तिक २७ गते गाई तिहार/औँशी [[लक्ष्मी पूजा|लक्ष्मीपूजा]]का दिन जन्मेका हुनाले यिनको नाम लक्ष्मीप्रसाद राखिएको हो, तर उनको न्वारानको नाउँ तीर्थमाधव देवकोटा हो। <ref>{{Cite web |last=पराजुली |first=गोपाल |date=2022-07-27 |title=महाकवि लक्ष्मीप्रसाद देवकोटा |url=https://www.gorkhapatra.org.np/mag/muna.detail.php?article_id=223&cat_id=17 |url-status=dead |archive-url=https://web.archive.org/web/20131206120800/https://www.gorkhapatra.org.np/mag/muna.detail.php?article_id=223&cat_id=17 |archive-date=2013-12-06 |access-date=2022-07-27 |website=गोरखापत्र |language=नेपाली }} {{Webarchive|url=https://web.archive.org/web/20131206120800/https://www.gorkhapatra.org.np/mag/muna.detail.php?article_id=223&cat_id=17 |date=2013-12-06 }}</ref><ref>{{Cite web |last=Sharma |first=Kumar |date=2014-10-23 |title=Mahakavi Devkota: The legend lives on |url=https://kathmandupost.com/miscellaneous/2014/10/23/mahakavi-devkota-the-legend-lives-on |url-status=live |access-date=2022-07-27 |website=The Kathmandu Post|language=अङ्ग्रेजी}}</ref>देवकोटाका बुबा संस्कृतका विद्वान् थिए। त्यसैले उनले आफ्नो आधारभूत शिक्षा बुबाको संरक्षकत्वमा प्राप्त गरेका थिए। उनले [[दरबार हाई स्कुल]]मा औपचारिक शिक्षाको सुरुवात गरेका थिए। उनले संस्कृत व्याकरण र अङ्ग्रेजी दुवैको अध्ययन गरेका थिए। देवकोटा दरबार हाई स्कुलमा नै आफ्ना साथीहरूलाई कविता सुनाउने गर्थे । उनका प्रायः साथीहरूले ती कविता देवकोटाले नै लेखेका हुन् भनेर स्वीकार्दैनथे । यसै क्रममा एक दिन सबै विद्यार्थी मिलेर यिनको बेइज्जत गर्ने हिसाबले कविता लेख्ने परीक्षा लिए । यिनले पनि सबै विद्यार्थीमाझ कविता लेखे अनि त्यसै घडी शिक्षकहरूले उनलाई ‘कोपिलाउँदो कवि’को दर्जा दिए। सन् १९२५ मा देवकोटा [[त्रि-चन्द्र कलेज]]मा विज्ञान विषयमा भर्ना भए। विज्ञानमा प्रमाणपत्र तहको अध्ययन पूरा गरेपछि उनी मानविकी सङ्कायमा सरेका थिए। सन् १९२९ मा आफ्नो स्नातक तहको अध्ययन पूरा गरेपछि, सन् १९३१ मा छात्रवृत्ति लिएर अङ्ग्रेजीमा स्नातकोत्तर पढ्ने आशामा उनी भारतको पटना गएका थिए। अङ्ग्रेजी विषयमा स्थान नपाएपछि उनले कानून पढेका थिए। आफ्नो परिवारको आर्थिक अवस्थाले गर्दा आफ्नो स्नातकोत्तर पूरा गर्ने उनको इच्छा अपूर्ण बनेको थियो।<ref>{{Cite web |last=लम्साल |first=युव नाथ |date=2013-12-06 |title=महाकवि: लक्ष्मीप्रसाद देवकोटा |url=https://www.gorkhapatra.org.np/gopa.detail.php?article_id=20008&cat_id=10 |url-status= |archive-url=https://web.archive.org/web/20131206120225/https://www.gorkhapatra.org.np/gopa.detail.php?article_id=20008&cat_id=10 |archive-date=2018-04-25 |access-date=2013-12-06 |website=गोरखापत्र }} {{Webarchive|url=https://web.archive.org/web/20131206120225/https://www.gorkhapatra.org.np/gopa.detail.php?article_id=20008&cat_id=10 |date=2013-12-06 }}</ref> देवकोटा जन्मेदेखि नै उनका घरमा अनेक कष्टहरूको प्रवेश भइरह्यो। उनको घरको व्यवस्थापकीय ढाँचा पनि अत्यन्तै दयनीय थियो। साथै उनको घरले गरिबीको रेखाबाट उम्किन पनि सकेको थिएन। त्यसैले उनी सानैमा भन्थे, ‘म अङ्ग्रेजी पढ्छु र धेरै पढेपछि ट्युसन पढाएर पैसा कमाउँछु। देवकोटाले बाल्यकालमा नै अमरकोश घोकेका थिए र स्तोत्रमाला पढेका थिए। उनी सानैदेखि आफ्ना बुबाको कविता साफी गर्थे। आफ्ना बुबाको कविता सार्दासार्दै उनी भित्र पनि साहित्यको रस बस्न थालेको थियो। उनलाई उनका बुबाले पण्डित बनाउन खोजेका थिए। == साहित्यिक यात्रा== देवकोटा बहुमुखी प्रतिभका धनी एवम् असाधारण लेखक थिए। दस वर्षको उमेर देखि नै कविता लेखनको सुरुवात गरेका उनको छोटो जीवनमा उनले नछोएको साहित्यको कुनै विधा छैन। उनले महाकाव्य, खण्डकाव्य, लामा वर्णनात्मक कविताहरू, निबन्धहरू, कथाहरू, नाटक, गीतहरू र समालोचनाहरू लेखेका छन्। कविता पढेजस्तै अनुभव हुने देवकोटाका निबन्धहरू शैली र विषयवस्तुका लागि एकदमै प्रशंसायोग्य छन्। देवकोटाले आधुनिक नेपाली भाषाको रोमान्टिक आन्दोलन सुरु गरेर नेपाली साहित्यमा योगदान दिएका थिए। नेपाली साहित्यमा [[महाकाव्य]] लेखन सुरु गर्ने उनी नेपालमा जन्मिएका दोस्रो लेखक थिए। साहित्यमा भाषाको नवीन प्रयोगसँगै नेपाली कविता देवकोटाको समयमा नयाँ उचाईमा पुगेको थियो। त्यतिबेला नेपाली साहित्यिक दृश्यमाथि प्रभुत्व जमाएको संस्कृत परम्परा त्यागेर [[नेवारी भाषा|नेपाल भाषा]]को ''जि वया ला लछि मदुनी''बाट प्रेरित भएर उनले [[मुनामदन]] (विसं १९९३) लेखेका थिए। लोकप्रिय झ्याउरे छन्द(भाका)मा उनले लामो आख्यानात्मक कविता लेखेका थिए। मुनामदन नेपाली साहित्यको इतिहासमै निकै उत्कृष्ट पुस्तक हो। ७६औँ एकेडेमी पुरस्कारमा सर्वोत्कृष्ट विदेशी भाषाको चलचित्रका लागि नेपालको आधिकारिक प्रवेश भएको सन् २००३ को चलचित्र मुनामदन यही खण्डकाव्यमा आधारित थियो। यो कार्यले त्यतिबेलाका देशका शासकहरू अर्थात् राणाहरूबाट तत्कालै मान्यता पाएको थियो। 'मुनामदन'मा मुना आफ्ना पति यात्रारत व्यापारी मदनको कथा सुनाउँछिन्। श्रीमती मुनालाई छोडेर केही पैसा कमाउनका लागि ऊ तिब्बत प्रस्थान गर्छ। खण्डकाव्यमा यात्राको विषयगत कष्ट, वियोगको शोक, तिर्सनाको चञ्चलता र मृत्युको पीडाको वर्णन गरिएको छ। देवकोटाद्वारा लिखित वियोगान्त खण्डकाव्य [[मुनामदन]] देवकोटाको मृत्युको पाँच दशक पछिसम्म पनि साझा प्रकाशनद्वारा अत्यधिक बिक्री हुने कृतिमा पर्दछ। ´मुनामदन` नेपाली जनजीवनमा भिजेको पहिलो नेपाली कृति हो। <ref>{{Cite web |last=गौतम |first=प्रभाकर |date=2019-06-29 |title=नेवारी गीतिकाव्य ‘जि वया ला लछि मदुनी’ बाट प्रभावित थियो देवकोटाको मुनामदन |url=https://www.setopati.com/art/art-activity/183642/ |url-status=live |access-date=2022-07-27 |website=सेतोपाटी |language=नेपाली }} {{Webarchive|url=https://web.archive.org/web/20220728021101/https://www.setopati.com/art/art-activity/183642/ |date=2022-07-28 }}</ref> ''जि वया ल लछी मदुनी'' एक नेवार व्यापारी, उनकी आमा र श्रीमतीमा आधारित एउटा दुखद गीत हो। व्यापारीले कामका लागि काठमाडौँ छाड्छ र तिब्बत तिर प्रस्थान गर्दछ। यो गीत श्रीमतीले सासूलाई उनको श्रीमानलाई जान नदिन बिन्ती गर्दा सुरु हुन्छ। काठमाडौँमा हुर्केका देवकोटाले स्थानीयले गाएको यो गीत फल्चामा सुनेका थिए। यो गीतबाट उनी अत्यन्तै मोहित भए र नेपाली भाषामा पुन: लेख्ने निधो गरेका थिए। राणा शासकहरूले नेवारी व्यापार, भाषा र साहित्यमाथि प्रतिबन्ध लगाउने भएकाले उनले मूल गीतमा जस्तै नेवार व्यापारीबाट मुख्य पात्रपरिवर्तन गरी क्षत्रिय (योद्धा वर्ग) चरित्रमा परिवर्तन गरेका थिए। क्षेत्री मानिसहरूले ती दिनहरूमा आफ्नो जीविकाको लागि व्यापार नगर्ने भए तापनि राणा शासकहरूलाई लोभ्याउन तिनले यसलाई त्यस्तो चित्रण गर्नुपरेको थियो। यस खण्डकाव्यबाट सबैभन्दा प्रसिद्ध र बारम्बार उद्धृत गरिएको श्लोक मध्ये एक यस्तो छ: <poem> "क्षेत्रीको छोरो यो पाउ छुन्छ, घिनले छुँदैन मानिस ठूलो दिलले हुन्छ जातले हुँदैन !" </poem> उत्कृष्ट कृतिको रूपमा मुनामदन नेपाली साहित्यका सामान्य पाठकमाझ निकै लोकप्रिय रहँदै आएको छ।<ref>{{Cite web |last=Acharya |first=Tulasi |date=2022-04-16 |title=The Nepali literary environment |url=https://kathmandupost.com/columns/2022/04/16/the-nepali-literary-environment |url-status=live |archive-url=https://web.archive.org/web/20220417105143/https://kathmandupost.com/columns/2022/04/16/the-nepali-literary-environment |archive-date=2022-04-17 |access-date=2022-07-27 |website=The Kathmandu Post |language=अङ्ग्रेजी}}</ref> यो वि. संं. १९९३ देखिको सबैभन्दा लोकप्रिय नेपाली पुस्तक रहेको छ भने यसलाई चिनियाँ भाषामा समेत अनुवाद गरिएको थियो। यसलाई चीनले राम्रोसँग ग्रहण गरेपछि यसलाई सफल ठानिएको थियो।<ref>{{Cite web |last=Mahat |first=Sunny |date=2019-01-04 |title=‘Muna Madan’ in Mandarin |url=https://theannapurnaexpress.com/news/books-in-translation-1067 |url-status=live |archive-url=https://web.archive.org/web/20220509182715/https://theannapurnaexpress.com/news/books-in-translation-1067 |archive-date=2022-05-09 |access-date=2022-07-28 |website=The Annapurna Express |language=अङ्ग्रेजी}}</ref> देवकोटाले सन् १९३९ मा मानसिक शरणमा रहेको पाँच महिने प्रवासबाट प्रेरित भएर मुक्तक कविता 'पागल' लेखेका थिए। यो कविता उनको असामान्य मानसिक क्षमतासँग सम्बन्धित छ र नेपाली भाषाका उत्कृष्ट कविताहरू मध्ये एक मानिन्छ। <poem> "जरुर साथी म पागल ! यस्तै छ मेरो हाल । म शब्दलाई देख्दछु ! दृश्यलाई सुन्दछु ! बासनालाई संवाद लिन्छु । आकाशभन्दा पातालका कुरालाई छुन्छु । ती कुरा, जसको अस्तित्व लोक मान्दैन जसको आकार संसार जान्दैन !...." </poem> [[File:Laxmi Prasad Devkota.jpg|alt=Laxmi Prasad Devkota|thumb|महाकवि देवकोटा]] देवकोटासँग धेरै छोटो समयमा साहित्यिक जटिलता र दार्शनिक घनत्वसहितलामो महाकाव्य र कविता रचना गर्ने क्षमता थियो जसअन्तर्गत उनले [[शाकुन्तल (महाकाव्य)|शाकुन्तल]] महाकाव्यको रचना गरेका थिए। उनको पहिलो महाकाव्य कविता र नेपाली आधुनिक महाकाव्यको जगतमा उनले तीन महिनामै यसको लेखन कार्य सकाएका थिए। सन् १९४५ मा प्रकाशित शाकुन्तल [[कालिदास]]को प्रसिद्ध संस्कृत नाटक [[अभिज्ञानशाकुन्तलम्]]मा आधारित छ। शाकुन्तलले देवकोटाको संस्कृत ज्ञान र शव्दकोशमा निपुणताको प्रदर्शन गर्दछ, जुन उनले मुख्यतया नेपालीमा रुपान्तरण गर्दा भारी मात्रामा गहन शब्दहरूको समावेश गरेका थिए। देवकोटाका दिवंगत विद्वान तथा अनुवादक डेभिड रुबिनका अनुसार शाकुन्तलले सबैभन्दा धेरै उपलब्धि हासिल गरेको छ। "यो, निसन्देहः एक उल्लेखनीय कृति, आधुनिक दृष्टिकोणसँग शास्त्रीय परम्पराका विभिन्न तत्वहरूलाई मिलाएर, ब्रह्माण्डीय लाक्षणिक, [[कालिदास]]को पार्थिव प्रेमको रोमान्टिक हाँस्यसँग मेल खान्छ, जसले कामुक र पवित्र प्रेमको सङ्गालोद्वारा मुक्तिको सङ्केत दिन्छ। देवकोटाले विभिन्न परम्परागत र गैरपरम्परागत विधामा स्थापित लघुगीतकविताका थुप्रै सङ्ग्रह पनि प्रकाशित गरेका थिए। उनका अधिकांश कविताले [[विलियम वोर्डस्वर्थ]] र कोलेरिज जस्ता अङ्ग्रेजी रोमान्टिक कविहरूको प्रभाव देखाउँछन्। कविता सङ्ग्रह ''[[भिखरी (कवितासङ्ग्राह)|भिखारी]]''मा रहेको शीर्षक कविता वर्ड्सवर्गको "द ओल्ड कम्बरल्यान्ड बेगर" को सम्झना हो। यस कवितामा देवकोटाले मानव प्रेम र भौतिक सुखसुविधाबाट बञ्चित भएर कठोर गरिबी र विध्वंशमा आफ्नो बाटो हिँडेको भिखारीको वर्णन गरेका छन्। अर्कोतर्फ भिखारीलाई दुःखकष्ट र दन्किरहेको अवस्थामा राखिएको अनुकम्पाको स्रोतको रूपमा पनि लिइन्छ। देवकोटाले भिखारीलाई दिव्यसँग दया र समानुभूतिको परम फन्दाको रूपमा जोडेका छन्: <poem> "कालो बादलबाट खसेको अन्धकारमा भित्र पसेको, ईश्वर हो कि भिखारी ? बोल्दछ ईश्वर हृदय घुसेका, घर, घर आँगन चारी बोल्दछ, आर्तध्वनिमा बोल्दछ करूणामृत दिल भारी ।...." </poem> देवकोटाका थुप्रै कविताहरू मानव र प्राकृतिक संसारका सांसारिक तत्त्वहरूमा केन्द्रित छन्। वन, किसान, बादल जस्ता उनका कविताका शीर्षकहरूले उनले विश्वका साझा र सम्बत पक्षहरूमा आफ्नो काव्यात्मक प्रेरणाको खोजी गरेको देखाउँछन्। उनका अधिकांश कविताहरूमा मानवताप्रतिको तिनको गहिरो विश्वासले गहिरो छाप पारेको छ। उदाहरणका लागि, वन भन्ने कवितामा वक्ताले व्यक्तिगत रूपले मात्र दिन सकिने सबै प्रकारका सान्त्वना तथा सान्त्वनाहरूलाई तिरस्कार गर्दै एकपछि अर्को केरकारहरू गर्छन्। यस कविताको अन्तमा वक्ताको मानवतावादी झुकावलाई प्रकाश पार्ने निम्न कवितांश प्रस्तुत गर्दछ: <poem> "दोस्त कहाँ छन्? साथ छ को को? घर हो तिम्रो कुन देश? जान्छौ कुन पुर भवन मुसाफिर, ल्यायौ कुन सन्देश? दोस्त मेरो शुभ उद्योगी, साथ छ साहस बेश । विश्व सबै घर, हृदय-पुरीतिर ल्याउँछु सेवा सन्देश ॥" </poem> देवकोटासँग कविताहरू एकदमै चाँडो लेख्‍ने अद्वितीय प्रतिभा थियो। उनले [[शाकुन्तल (महाकाव्य)]] तीन महिनामा, [[सुलोचना (महाकाव्य)]] दश दिनमा र [[कुञ्जिनी]] खण्डकाव्य एकै रातमा लेखे। उनले नेपाली साहित्यलाई नयाँ उचाइमा पुर्‍याए। प्रचलित लोक भाका अर्थात् झ्याउरे छन्दमा लेखिएको कृति मुनामदनले नेपाली साहित्यमा संस्कृतको प्रभावको अन्त्य गरेको थियो। "पागल" कविता उनको अर्को महान सिर्जना हो; जुन कवितामा उनले आफूलाई पागल भन्नेहरूलाई नै कवितात्मक शैलीमा जवाफ दिएका छन्| <ref>नेपाली साहित्य शृङ्खला, ''भाग २, प्रा. डा. बासुदेव त्रिपाठी''</ref> नेपाली भाषासाहित्यमा देवकोटा रूमानी प्रवृत्तिलेखन स्वच्छन्दवादका श्रीगणेश भए। साथै नेपाली भाषासाहित्यलाई अङ्ग्रेजी भाषासाहित्यमा अनुवाद गरेर सर्वप्रथम पश्चिमी मुलुकमा पुर्‍याउने काम पनि देवकोटाबाट नै भएको थियो। भारतीय महापण्डित डा [[राहुल साङ्कृत्यायन]]ले भनेका थिए, ‘मैले देवकोटालाई बुद्धपछिको सबैभन्दा ठूलो मानवअवतारका रूपमा लिएको छु।’ साङ्कृत्यायनले देवकोटालाई भारतका जल्दाबल्दा तीन कवि जयशङ्कर प्रसाद, सुमित्रानन्दन पन्त र सूर्यकान्त त्रिपाठी निराला बराबर एक जना देवकोटा हुन् भनेका थिए। <ref>महाकवी लक्ष्मी प्रसाद देवकोटा जीवनी (१९०९-१९५९)</ref> देवकोटा चौध भाषा बुझ्थे। उनी द्वारा नौ भाषामा लेखिएका कविताहरू ´शारदा` मासिक मार्फत जनमाझ पनि आए। देवकोटालाई काव्यसागरका जलदेवता भने पनि हुन्थ। उनी उठ्ता, बस्ता, हिँड्दा, सुत्दा, खाँदा वा आफ्ना चेतन र अचेतनका कुनै पनि पलमा काव्यभन्दा बाहिर हुँदैन थिए। बिहान आँखा उघारेदेखि राति आँखा चिम्लेपछिको स्वप्नसंसारमा पनि उनी काव्यसंसारमा नै यात्रा गर्थे। उनको बाँचुन्जेलको साथी एउटा ´कविता` थियो र अर्को ´चुरोट` थियो। लेखेका बेला उनी आफ्नै पाण्डुलिपि बालेर चुरोट सल्काएको र त्यसैले सिँगान पुछेको पनि चाल पाउँदैन थिए। == राजनीति == [[चित्र:Laxmi Prasad Devkota Stamp.jpg|alt=Commemorative stamp of Devkota|thumb|247x247px| हुलाक टिकटमा देवकोटाक‍ तस्वीर]] लक्ष्मीप्रसाद देवकोटा कुनै पनि स्थापित राजनीतिक दलभित्र सक्रिय थिएनन् तर उनका कविताले निरन्तर रूपमा उत्पीडित राणा वंशका विरुद्ध विद्रोहको रवैयालाई मूर्तरूप दिएको थियो। वाराणसीमा स्वनिर्वासन हुँदा उनले [[नेपाली काङ्ग्रेस|नेपाली काङ्ग्रेस]]को युगवाणी पत्रपत्रिकाको सम्पादक भएर काम गर्न थालेका थिए। राणा सरकारले नेपालमा आफ्नो सबै सम्पत्ति जफत गरेको थियो। === लाइब्रेरी पर्व === {{मुख्य|लाइब्रेरी पर्व}} [[भीम शमशेर जङ्गबहादुर राणा|भीमशमशेर]]ले देशमा नेपाली, हिन्दी, अङ्ग्रेजी र नेवारीमा भाषाको उन्नति गर्न भनेर इस्तिहार जारी गरे । यो खबर पाएर काठमाडौंका केही युवाहरूले पठन संस्कृतिको विकास तथा देशविदेशका कुरा थाहा पाउन एउटा पुस्तकालयको आवश्यकता महसुस गरे । त्यस्तो पुस्तकालय महेन्द्रबहालमा राख्ने योजनासहित ४५ जना युवाहरूले श्री ३ भीम शम्शेरसमक्ष निवेदन पेस गर्न हस्ताक्षर अभियान चलाए । हस्ताक्षर गराउने मुख्य जिम्मा बैकुण्ठप्रसाद लाकौलले पाएका थिए । केही समयपश्चात हस्ताक्षर संकलन समेत भईवरी दरबारमा पत्र बुझाइयो । तर हस्ताक्षर नगर्ने रामचन्द्र अधिकारी नामक अर्का युवाले हस्ताक्षरकर्ता युवाहरूको अभियान राजनीतिक उद्देश्यको भएको र उनीहरूले श्री ३ को गाथगादी ताकेका छन् भन्ने उजुरी दरबारमा चढाए । यसरी सरस्वती गुठी नामक संस्था स्थापना गरी त्यसमार्फत् पुस्तकालय खोल्ने कार्यलाई राजनीतिक आवरणको आरोप लागेपछि दरबारले पत्रका हस्ताक्षरकर्ता सबैलाई पक्राउ गर्न उर्दी जारी गर्‍यो । अधिकांश हस्ताक्षरकर्ताहरूलाई पक्राउ गरी बयान लिने क्रममा उक्त घटनालाई 'लाइब्रेरी पर्व' भनी मुद्दा जाहेर भयो । बि‍. सं १९८७ साल वैशाख १६ र १७ गते दुई दिन गरी पुस्तकालय खोल्ने अभियानका युवाहरूलाई पक्राउ गरियो । त्यसरी पक्राउ परेका युवाहरूलाई दरबारबाट बिभिन्न सजाय तोकियो । ती मध्ये उमेश शाहलाई देश निकाला र मैनाबहादुर, खड्गमान, रंगनाथ आदिलाई जन्मकैदको सजाय सुनाइएको थियो । [[लक्ष्मीप्रसाद देवकोटा]], [[सिद्धिचरण श्रेष्ठ]], [[कृष्णप्रसाद कोइराला]]लगायतलाई रु. १०० जरिवाना र अबका १२ वर्ष जनस्तरका कुनै कार्य गर्ने छैन भन्ने कागज गराई छोडिएको थियो । राज खानदानका भएर पनि दुनियाँका छोराहरूका साथ हिँडेको भनी जितेन्द्र बहादुर शाह र पद्म शाहलाई जनही रु. १००० जरिवाना गरिएको थियो । पुस्तकालय खोल्न पाऊँ भनी पत्रमा हस्ताक्षर गर्ने ४५ जना युवाहरूमा महाकवि लक्ष्मीप्रसाद देवकोटा, सिद्धिचरण श्रेष्ठ, कृष्णप्रसाद कोइराला, [[चित्तधर हृदय]], योगवीरसिंह कंसाकार, वैकुण्ठप्रसाद लाकौल, [[तुलसीमेहर श्रेष्ठ|तुलसी मेहर]], शंकरप्रसाद नेपाल, [[महेन्द्र विक्रम शाह|महेन्द्रविक्रम शाह]], [[शङ्करदेव पन्त|शंकरदेव पन्त]]जस्ता साहित्य, भाषा, शिक्षा तथा सामाजिक सांस्कृतिक क्षेत्रमा प्रसिद्ध युवाहरू थिए ।<ref>{{Cite news|url=https://ekantipur.com/bibidha/2023/04/29/168267052220824323.html|title='लाइब्रेरी पर्व'को महत्त्व र राष्ट्रिय लेखक दिवसको औचित्य|last=नेपाल|first=रत्नमणि|date=वैशाख १६, २०८०|work=कान्तिपुर}}</ref> सार्वजनिक पुस्तकालय खोल्छु भन्नेलाई [[भीम शमशेर जङ्गबहादुर राणा|भीमशमशेर]]ले जेलमा कोचे। यस्तो धोखाधडीका कारण पनि उनी इतिहासमा बदनाम छन्। [[लाइब्रेरी पर्व]]ले भीमशमशेरको अनुदार छवि प्रस्तुत गर्छ। ===सल्लाहकार समिति सदस्य=== वि.सं. २००७ सालको क्रान्तिमार्फत प्रजातन्त्रको परिचय गराएपछि देवकोटालाई राजा त्रिभुवनद्वारा वि.सं. २००८ मा नेपाल सल्लाहकार समितको समूहको सदस्यमा नियुक्त गरिएको थियो। उक्त सल्लाहकार सभाको अध्यक्षका लागि नेपाली कांग्रेसका महामन्त्री [[कृष्णप्रसाद भट्टराई]] र लक्ष्मीप्रसाद देवकोटाले उम्मेदवारी दिएका थिए । मतदानमा भट्टराईले ४० र देवकोटाले १४ मत पाए र भट्टराई अध्यक्ष (स्पिकर) चुनिए। <ref>{{Cite journal |last=Nepal |first=जगत Jagat नेपाल |last2=Kafle |first2=डोलराज Dolaraj काफ्ले |last3=Khatiwada |first3=महा प्रसाद Maha Prasad खतिवडा |date=2025-01-06 |title=प्रजातान्त्रिक नेपालको पहिलो संसद, सल्लाहकार सभा र मिडिया कभरेज |url=https://www.nepjol.info/index.php/vaikharivani/article/view/70312/55792 |journal=Vaikharivani |language=en |volume=2 |issue=1 |pages=69–78 |doi=10.3126/vaikharivani.v2i1.70312 |issn=3021-9833}}</ref> उक्त सल्लाहकार सभा २००९ भदौ १९ मा अन्त्य भयो । [[त्रिभुवन वीरविक्रम शाह|राजा त्रिभुवन]]को पालामा बुद्धिजीवी वर्गको प्रतिनिधिका रूपमा राजा त्रिभुवनबाट ‘सल्लाहकार सभा’मा उनी पुनः मनोनीत भएका थिए। सल्लाहकार सभा गठन हुँदा देवकोटालाई विपक्षी नेता बनाइएको थियो। सो सल्लाहकार सभाको दोस्रो अधिवेशनमा [[मातृकाप्रसाद कोइराला]]द्वारा प्रस्तुत बजेटमाथि विपक्षी दलका नेताका हैसियतले गरेको चर्को भाषणकै कारण सरकार विघटित हुनपुगेको थियो।<ref>[https://echitwanpost.com/92148/2019110211/44/40/ महाकवि देवकोटाको मूलदर्शन : अध्यात्म (व्यक्तित्व/कृतित्व चर्चा)]</ref> [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]]ले पनि देवकोटाको सो पदलाई निरन्तरता दिएका थिए। देवकोटा [[त्रिभुवन विश्वविद्यालय]]को स्थापनासँगै सो विश्वविद्यालयको समिति सदस्यमा मनोनीत भएका थिए। त्यसपछि उनैको हस्ताक्षरमा विश्वविद्यालयको रूपरेखा तयार भएको थियो। उनी पछि नेपाल प्रज्ञाप्रतिष्ठानका सदस्य पनि भएका थिए। === शिक्षा मन्त्री === [[कुँवर इन्द्रजीत सिंह|कुँवर इन्द्रजित सिंह]]को [[कुँवर इन्द्रजीत सिंह मन्त्रिपरिषद्|मन्त्रिपरिषद्मा]] देवकोटा शिक्षा, स्वायत्तशासन मन्त्री थिए । <ref>[http://rajpatra.dop.gov.np/welcome/book/?ref=1104०१४ साल श्रावण ११ गतेको नेपाल गजेट]</ref> शिक्षामन्त्री भएपनि देवकोटालाई शिक्षा मन्त्रालय कहाँ छ भन्ने थाहा थिएन र उनलाई [[सत्यमोहन जोशी]]ले गाडीमा मन्त्रालय पुर्‍याएका थिए। शिक्षामन्त्री छँदा उनले त्रिभुवन विश्वविद्यालय र प्रज्ञाप्रतिष्ठानको स्थापना गर्न महत्त्वपूर्ण योगदान गरेका थिए। [[कुँवर इन्द्रजीत सिंह मन्त्रिपरिषद्|केआई सिंहको प्रधानमन्त्रित्वमा गठित मन्त्रिपरिषद्मा]] उनी शिक्षा तथा स्वायत्त शासनमन्त्री पनि बनेका थिए। ११० दिनसम्म मन्त्री भएका बेला उनले नेपाल राष्ट्रभरिका विद्यालय र कलेजहरूमा नेपाली भाषामा पढाइ हुने व्यवस्था मिलाएका थिए। == तास्केन्त सम्मेलनमा सहभागी == [[चित्र:Madhav Prasad Ghimire with Laxmi Prasad Devkota 2.jpg|alt=Devkota with poet Madhav Prasad Ghimire|thumb|338x338px|महाकवि देवकोटा (दायाँ) [[माधवप्रसाद घिमिरे (साहित्यकार)|माधवप्रसाद घिमिरे]]सँग]] सन् १९५८ को अक्टोबरमा तत्कालीन सोभियत गणतन्त्र [[उज्बेकिस्तान]]को राजधानी [[तास्केन्त]]मा भएको अफ्रिकी–एसियाली लेखक सम्मेलनमा देवकोटाले नेपाली मण्डलको नेतृत्व गरेका थिए। त्यतिबेला [[नेपाली काङ्ग्रेस]]को सरकार थियो। उनले राजासँग स्वीकृति नलिई सरकारसँग स्वीकृति लिएका थिए। त्यतिबेला [[भारत]]को [[नयाँ दिल्ली]]बाट [[प्रवेशाज्ञा|भिसा]] लिँदै उनी र [[माधवप्रसाद घिमिरे (साहित्यकार)|माधव प्रसाद घिमिरे]] तास्केन्त पुगेका थिए। देवकोटाले राजासँग स्वीकृति नलिएर राजाको अनादार गरे भनेर उनको विरोध भएको थियो। राजा [[नेपाल प्रज्ञा प्रतिष्ठान|प्रज्ञा प्रतिष्ठान]]को कुलपति थिए। देवकोटा कम्युनिस्ट भयो भनेर उनको विषयमा [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]]लाई कुरा लगाउने काम गरिएको थियो। उनले [[नेपाली भाषा]] साहित्यको विषयमा त्यहाँ बुलन्द भाषण गरेका थिए। तर यता देशको नाम बदनाम गर्‍यो भनेर राजालाई उचाल्ने काम भएको थियो। [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]]ले पनि उनको तीन महिनाको तलब जरिवानाबापत रोक्का गरिदिएका थिए। यस घटनाले उनी निराश बनेका थिए। पछि [[श्यामदास वैष्णव]]सँग आफ्नो निराशा व्यक्त गर्दै भनेका थिए "धेरै बाँचियो ! बाँच्न पुग्यो।" <ref name=":1">श्यामदास वैष्णव ; आफू जलेर उज्यालो दिने मैन ; नागरिक दैनिक २०६९ कार्तिक २५</ref> देवकोटा नेपालबाट [[प्रवेशाज्ञा]] र [[राहदानी]] नबनाई तास्केन्त गएका थिए। त्यसका निम्ति उनलाई मन्त्रिपरिषद्का अध्यक्ष [[सुवर्ण शमशेर राणा|सुवर्णशमशेर]]देखि [[नेपाल प्रज्ञा प्रतिष्ठान|शाही नेपाल प्रज्ञाप्रतिष्ठान]]का उपकुलपति [[बालचन्द्र शर्मा]]सम्मले हरियो झण्डा देखाएर प्रेरित गरेका थिए। तर पछि तिनै व्यक्तिहरूको सिफारिसमा नै देवकोटाले प्रज्ञाप्रतिष्ठानबाट पाउने पारिश्रमिक रोक्का गरिएको थियो। तर पछि त्यसको रहस्य खुलेपछि एक महिनाको तलब जरिमाना गरेर [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]]ले उनको पारिश्रमिक निकासा गरिदिएका थिए।<ref name=":1" /> == व्यक्तिगत जीवन == देवकोटाको १५ वर्षको उमेरमा मनदेवी चालिसेसँग विवाह भएको थियो। वि.सं. १९८५ मा उनको पहिलो सन्तान स्वरूप छोरी सावित्री र वि.सं. १९८९ मा जेठो छोराको रुपमा प्रकाशको जन्म भएको थियो। माहिला छोरा कृष्णप्रसाद देवकोटाको जन्म वि.सं. १९९३ मा भएको थियो। देवकोटाका छोरा पदम देवकोटा कवि तथा लेखक हुन्। उनी [[त्रिभुवन विश्वविद्यालय]]को अङ्ग्रेजी विभाग, काठमाडौंमा धेरै वर्ष प्राध्यापकको रूपमा कार्यरत थिए।<ref>{{Cite web |date=2022-02-01 |title=A Concocted Emotion Is not Poetry: Padma Devkota |url=https://thegorkhatimes.com/2022/02/01/a-concocted-emotion-is-not-poetry-padma-devkota/ |access-date=2022-05-15 |website=The Gorkha Times |language=अङ्ग्रेजी}}</ref> देवकोटाले कानुनमा स्नातको उपाधि हासिल गरेपछि उनी आफ्नो घर फर्के; जहाँ उनले विभिन्न व्यक्तिगत सङ्कटहरू भोग्नु परेको थियो। दुई वर्ष भित्रै उनका बुवा, आमा र दुई वर्षे छोरीको मृत्यु भएको थियो। ती वियोगान्त घटनाहरूले उनलाई मर्माहत तुल्याउँदा यसैबाट उनीमा चुरोटको लत बसेको थियो। पछिल्ला वर्षहरूमा उनका कलिला छोराहरू प्रकाश र कृष्णको असामयिक मृत्युले उनी झन् मर्माहीत भएका थिए र यसले उनको मस्तिष्कलाई समेत चोट पुर्‍याएको थियो। मानसिक समस्याहरूबाट गुज्रिरहेका देवकोटाले पाँच महिना [[भारत]]को राँचीमा अवस्थित मानसिक अस्पतालमा समेत समय बिताएका थिए। पछि आफ्नो जीवनमा आर्थिक ऋण र छोरीहरूको विवाह र दाइजोमा खर्च गर्न असमर्थ भएको कारण उनले एक पटक आफ्नी श्रीमतीलाई यसो भनेका थिए, "आज राती हामी बच्चाहरूलाई समाज र युवाको हेरचाहमा त्यागौँ र सुत्ने समयमा यस संसारलाई त्यागौँ, पोटासियम साइनाइड वा मोर्फिन वा यस्तै केही गरौँँ"। == अन्तिम वर्ष र मृत्यु == [[चित्र:Laxmi Prasad Devkota 1.jpg|alt=A photo of Devkota smoking (2013 BS (1956-1957))|thumb|चुरोट पिउँदै गरिरहेका कवि देवकोटा, विसं २०१३ साल]] लक्ष्मीप्रसाद देवकोटा जीवनकाल भरिनै निकै धुम्रपान गर्ने व्यक्ति थिए। देवकोटालाई वि.सं. २०१५ मा क्यान्सर लागेको थाहा भएको थियो। २०१६ सालमा उपचारका लागि सुरुमा भारत लगियो। त्यहाँ उनको आन्द्रा काटियो। पछि रुस लगियो। रुसका चिकित्सकहरूले सबैलाई गाली गरे। उनको आन्द्रा काट्नै नपर्ने भनेर। अब बिजोग भयो। भारतमा जचाँउदा आन्द्रै काटिदियो। रुसमा आन्द्रा काट्नै नपर्ने भन्यो। रोग लागेपछि उनको जीवन थप कष्टकर बन्यो।<ref name=":1" /> [[भारत]] लगेर ठूलो आन्द्राको ३ इन्च निकालिएपछि उनलाई आफू मृत्युको मुखमा आएको पक्का भएको थियो। त्यसपछि उनी रातभर जाग्राम बसी आफ्ना रचना लेख्न थालेका थिए। आफ्नो रोगको उपचारका लागि आवश्यक औषधि खरिद गर्न नसकेको दाबी गरेका थिए, यसबाहेक उनले खानासमेत किन्न निकै सङ्घर्ष गरिरहेका थिए। शान्त भवन अस्पतालमा रहँदा उनले आफ्ना साथी हरि श्रेष्ठलाई चिठीमा लेखेका थिए जुन यस प्रकार छ "मृत्यु मेरो अगाडि छ। म आकाशमा नक्षत्रहरू खोज्छु तर भेट्दिनँ। म आफूलाई शान्ति दिन सक्दिनँ । म उठ्न सक्ने भएँ, म आफू र आफ्ना बच्चाहरूलाई मार्ने थिएँ ।" जीवनभर, उनले भगवान् मानेनन् । आर्यघाटमा उनले भने 'मैले आफ्नो जिन्दगी हरिनाम नजपेर ,नास्तिक भएर बिताएछु, अब जान आँटिहालेँ" अनि उनले जीवनको शाश्वत आध्यात्मिक कुरा कवितामार्फत यसरी व्यक्त गरे। <ref>श्रेष्ठ, स्वयम्भूलाल, भानु, महाकवि देवकोटा विशेषाङ्क (२०२५ फागुन),'''महाकवि देवकोटा : संक्षिप्त जीवनी र केही क्षण''', भद्रपुर : भानु प्रकाशन</ref> :संसार रूपी सुख स्वर्गभित्र, :रमें, रमाएँ लिई भित्र चित्र । :सारा भयो त्यो मरूभूमि तुल्य, :रातै परेझैँ अब बुझ्छु बल्ल ॥१॥ :रहेछ संसार निशा समान, :आएन ज्यूँदै रहँदा नि ज्ञान । :आखिर श्रीकृष्ण रहेछ एक, :न भक्ति भो, ज्ञान, न भो विवेक ॥२॥ :महामरूमा कणझैँ म तातो, :जलेर मर्दो बिनु आश लाटो । :सुकी रहेको तरूझैँ छु खाली, :चिताग्नि तापी जल डाम्न फाली ॥३॥ :संस्कार आफ्नो सब नै गुमाएँ, :म शून्यमा शून्य सरी बिलाएँ । :जन्मे म यो स्वर्ग विषे पलाएँ, :आखिर मै खाक त्यसै बिलाएँ ॥४॥ शान्तभवनमा उनलाई हेर्न भीड लाग्ने गर्थ्यो। एकदिन [[राजा महेन्द्र]] उनको स्वास्थबारे जानकारी लिन आएका थिए। राजाले महाकविलाई सोधे , "तिमीलाई के चाहिन्छ?" त्यतिबेला देवकोटाले भने, "केही चाहिदैन सरकार, एउटा चुरोट भए पुग्छ।" त्यसपछि राजाले डुमरिया ब्रान्डको चुरोट खल्तीबाट निकालेर दिए।<ref>{{Cite news|title=एउटा चुरोट भए पुग्छ|last=केसी|first=विमलासिंह|date=२०६९ कार्तिक २५|work=नागरिक दैनिक}}</ref> उनलाई निको पार्न नसकिने पक्कापक्की भएपछि शान्तभवन अस्पतालबाट पशुपति आर्यघाटमा लाने मेलोमेसो गरिएको थियो । त्यस बेलासम्ममा देवकोटा चेतनशील थिए र उनलाई आफ्नो सम्भावित मृत्युको बारेमा पनि धेरै कुराको ज्ञान भइरहेको थियो। त्यति बेलासम्म पनि डा. एडगार आर. मिलरले महाकवि देवकोटालाई रगत दिएर थप केही दिन बचाउने इच्छा दर्शाएका थिए । तर उनको प्रस्तावमा देवकोटाले भनेका थिए, ‘‘डाक्टर ! किन यी युवकका रगत खेर फाल्ने ? तपाईंलाई थाहा छ, म मर्ने भैसकेको छु । टार्न नसकिने कुरालाई किन लम्ब्याउने ?’’<ref name=":2">{{Cite web |last=प्रसाई |first=नरेन्द्रराज |date=कात्तिक २९, २०७७ |title=महाकवि देवकोटाको जीवनको अन्तिम क्षण |url=https://baahrakhari.com/detail/296339 |access-date=2025-04-26 |website=बाह्रखरी }}{{Dead link|date=May 2026 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> देवकोटालाई रगत दिएर बचाउनेहरूप्रति उनले भदौ २६ गते कृतज्ञता ज्ञापन गरे । “दुई साहसी युवक भतिजा पद्मनाथ देवकोटा (लेखनाथ देवकोटाका कान्छा छोरा) र भोलामानसिंह थापा (पछि सहायक मन्त्री) ले मलाई रक्त प्रदान गरी २–४ दिनदेखि आजसम्म जियाए । उनीहरू चिरायु होऊन् । अब म मानवरक्त लिन्न र दिन चाहने व्यक्तिलाई धन्यवाद दिन्छु ।”<ref name=":2" /> देवकोटाको पीडा असह्य थियो र मर्नु पनि निश्चित भइसकेपछि उनी विष घुड्क्याएर भए पनि चाँडै क्यान्सरग्रस्त चोला बिसाउन पाए सन्चो हुन्थ्यो भन्ने चिन्तामा थिए । अस्पतालबाट पशुपति हिँडाइने बेलामा उनलाई हेर्न वासुदेव शर्मा लुइँटेल पनि शान्तभवन पुगेका थिए । लुइँटेल र देवकोटा खुबै मिल्थे । वास्तवमा लुइँटेलले देवकोटालाई सधैँ आदर, सम्मान र श्रद्धा नै गरिरहेका थिए । त्यसैले लुइँटेललाई भेट्नेबित्तिकै देवकोटाले आत्मीयता बाँड्दै भने “मलाई अलिकति विष ल्याइदिनुभएको छ ? मलाई डाहा भइरहेछ ! मलाई चाँडै मारिदिनुहोस् तपाईंलाई धर्म हुन्छ । पण्डितजी ! मलाई विष खान दिनुहोस् म मर्छु ।”<ref name=":2" /> देवकोटाले मृत्युशय्यामा बसेर नेपाली र अंग्रेजी भाषामा तीनवटा कविता लेखे । उनले त्यति बेला लेखेको अन्तिम नेपाली कविता एउटा ‘शून्यमा शून्यसरी’ अंग्रेजीमा लेखेको ‘लाइफ अफ द रिचेस्ट’ हरि श्रेष्ठलाई दिए । साथै उनले अंग्रेजी भाषामा लेखेको अन्तिम कविता ‘प्रमिथियन पेन आई बियर’ चाहिँ डा. एडगार आर. मिलरलाई दिएका थिए । देवकोटा अस्पतालको शय्यामा छटपट–छटपट नै गरिरहेका थिए । उनको वेदना, चित्कार र अवस्था देख्नेजति सबैका आँखा त्यस बेला रसाइरहेका हुन्थे । उनी क्रन्दनको ज्वाला फुटाएर भनिरहेका थिए “म किन बाँचिरहेको छु ?” आर्यघाट लाने बेलामा उनलाई सेतो भोटो र सुरुवाल फेराइएको थियो । अन्तिम यात्रा स्वरूप शान्तभवन अस्पतालमा उनलाई मोटरमा राखियो । उनी सुतेको मोटर २०१६ साल भदौ २७ गते बिहान ५.३० बजे पशुपति आर्यघाटतिर हुइँकियो । त्यति बेला आफन्तमाझ उनले भनिरहेका थिए, “अब म चौबीस घण्टाभन्दा बढी बाँच्न पाउँदिनँ ।” ===मृत्यु=== उनको मृत्युलाई यति तमासा बनाइयो। रोगले थलिएर हाडछाला मात्र भएका देवकोटाको फोटो खिच्ने र कविता बाचन गर्न लगाइने काम भयो। भदौ २९ गते प्रधानमन्त्री [[विश्वेश्वरप्रसाद कोइराला|बीपी कोइराला]]का तर्फबाट निर्माण तथा सञ्चार मन्त्री [[गणेशमान सिंह]]ले पशुपति आर्यघाट पुगी महाकवि देवकोटासँग उनको अन्तिम इच्छाबारे सोधेका थिए । मन्त्री सिंहसंग देवकोटाले आफ्नो ऋण र छोराहरुको पढाइबारे चिन्ता व्यक्त गरे । त्यो बेला महाकविको २२ हजार ऋण रहेछ । सरकारले पूरै ऋण तिर्ने बचन दिएकै दिन उनको निधन भयो । <ref name=":0" /> क्यान्सर रोगसँगको लामो सङ्घर्षपछि देवकोटाको विसं २०१६ साल भाद्र २९ साँझ ([[मदनमणि दीक्षित|मदनमणि दिक्षित]]को अनुसार ६ बजे) [[काठमाडौँ]]को [[पशुपतिनाथ मन्दिर]]स्थित बागमती नदीको किनारमा रहेको [[आर्यघाट]]मा निधन भएको थियो। === प्रतिकृया === भदौ २९ गते सरकारले महाकविको शोकमा दिउँसो २ बजेपछि सिंहदरबार सचिवालय र अरु अड्डामा बिदा दियो भने सबै शिक्षण संस्था एक दिन बन्द गरिए । देवकोटाको निधनप्रति दुःख व्यक्त गर्दै प्रधानमन्त्री [[विश्वेश्वरप्रसाद कोइराला|बीपी कोइराला]]ले २०१६ भदौ ३० गते [[प्रतिनिधि सभा (नेपाल)|प्रतिनिधि सभा]] बैठकमा भनेका थिए— “नेपाली साहित्य जगतका एक महान् विभूति महाकवि देवकोटाको असामयिक निधनबाट देशलाई ठूलो क्षति भएको छ। नेपालको सबभन्दा ठूलो साहित्यिक, मलाई त यो भन्नमा अत्युक्ति लाग्दैन कि नेपाली साहित्यको इतिहासको सबभन्दा ठूलो व्यक्तिको निधन भयो।” प्रधानमन्त्रीले प्रतिनिधि सभा र महासभामा बैठक स्थगन प्रस्ताव राखेपछि दुवै सदनमा २ मिनेट मौन धारण गरेर महाकविप्रति श्रद्धाञ्जली अर्पण गरियो ।<ref name=":0">{{Cite news|url=https://anweshannews.com/news/details/259|title=सरकारले तिरेको थियो, महाकविको २२ हजार ऋण|last=अन्वेषण सम्वाददाता|work=अन्वेषण}}{{Dead link|date=July 2025 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> महाकविप्रति श्रद्धाञ्जली अर्पण गर्दै [[नेपाल राष्ट्रवादी गोर्खा परिषद्|राष्ट्रिय गोरखा परिषद्]] नेता मृगेन्द्रशमशेर राणाले भने, “देवकोटा नेपालको साहित्यिकजगत्को मात्र होइन कि नेपालभरको एउटा तारा हुनुहुन्थ्यो । उहाँको निधन भो भन्ने त मलाई लाग्दैन । त्यसैले आज हामी उहाँलाई श्रद्धाञ्जली अर्पण गर्न आएका छौं भन्ने मलाई लाग्छ । त्यो विभूति हाम्रा अगाडि छैन । हामीमा ठूलो क्षति भएको छ । उहाँको मृत्यु भो भन्ने मलाई लाग्दैन उहाँ मर्नु भएको छैन । मर्नुहुने पनि छैन । जो मानिस १ करोड जनताको हृदयमा बसेको छ, त्यो मानिस मर्न सक्तैन, मर्ने छैन ।”<ref name=":0" /> [[नेपाल कम्युनिस्ट पार्टी]]का [[तुलसीलाल अमात्य]]ले भने, “देवकोटाजीको निधनले हाम्रो देशको साहित्यलाई मात्र होइन, संसारको साहित्यलाई नै एउटा ठूलो धक्का दिएको छ ।” <ref name=":0" /> == देवकोटाका केही प्रमुख कृतिहरू == '''१. कविता सङ्ग्रह:''' [[पहाडी पुकार]] ( वि. सं. २००५)•[[पुतली (बाल कविता)]]• वि. सं. २००९)• [[भिखारी]] ( वि. सं. २०१०) •[[सुनको बिहान]] ( वि.सं.२०१०) •[[छहरा]] (वि. सं. २०१२)• जन्मोत्सव र मुटुको थोपा ( वि.सं.२०१५) • [[मृत्युशैयाबाट]] ( वि. सं.२०१६) •[[चिल्ला पातहरू]] (मृत्युपश्चात प्रकाशित, वि.सं. २०२१) •गाइने गीतहरू (मृत्युपश्चात प्रकासित, वि.सं. २०२४) •मनोरञ्जन (मृत्युपश्चात प्रकाशित, वि. सं. २०२४) • [[भावना गाङ्गेय]] (मृत्युपश्चात प्रकाशित, वि. सं. २०२४)• [[आकाश बोल्छ]] (मृत्युपश्चात् प्रकाशित, वि. सं. २०२५) • [[छाँगासँग कुरा]] (मृत्युपश्चात् प्रकाशित, वि. सं. २०२६), •[[लक्ष्मी कविता सङ्ग्रह]] ( मृत्युपश्चात प्रकाशित, वि. सं. २०३३) • [[लक्ष्मी गीत सङ्ग्रह]] (मृत्युपश्चात प्रकाशित, वि. सं. २०४०) '''२.खण्डकाव्य :''' [[मुनामदन]] ( प्रकाशन वर्ष, वि. सं. १९९१) , [[राजकुमार प्रभाकर]] (वि. सं. १९९७), [[कुञ्जिनी]] (वि. सं. २००२), [[वसन्ती गीतीकाव्य]](वि. सं. २००९), [[मैनाचरी|मैना]] (वि. सं. २००९), [[सुन्दरी जर्पिना]] (वि. सं. २००९), [[रावण जटायु युद्ध]] (वि. सं. २०११) , [[म्हेन्दु]] (वि. सं. २०१५), [[लुनी]] (वि. सं. २०२३), [[सीताहरण]] (वि. सं. २०२४), [[मायाविनि सर्सी]] (वि. सं. २०२४), [[नवरस कोश काव्य]] (वि. सं. २०२५), [[मैनाचरी|मैना]] ( पुन: सम्पादन वि. सं. २०३९)। ३.'''निबन्ध''': [[आषाढको पन्ध्र]](वि. सं. १९९३,शारदा), [[भलादमी]], [[फूल]], [[पहाडी जीवन]], [[हाई हाई अङ्ग्रेजी]], [[के नेपाल सानो छ]], [[कला र जीवन]], [[कल्पना]], [[साधुको महात्म्य]], [[निद्रा श्रीपञ्चमीको दिन वि. सं. २०१०]], [[साँढे]],[[मेरो पाल्पा तानसेन तर्फको यात्रा]] आदि । {{Table |type=class="wikitable sortable" |title= लक्ष्मीप्रसाद देवकोटाका कविता सङ्ग्रहहरू |hdrs= प्रकाशन मिति!!शीर्षक!!विधा |row1= वि. सं. २००५ {{!!}} [[पहाडी पुकार]] {{!!}} कविता |row2= वि. सं.२००९ {{!!}} [[पुतली(बाल कविता)|पुतली]] {{!!}} कविता |row3= वि. सं.२०१० {{!!}} [[भिखारी]] {{!!}} कविता |row4= वि. सं. २०१० {{!!}} [[सुनको बिहान]] {{!!}} कविता |row5= वि. सं. २०१२ {{!!}} [[छहरा]] {{!!}} कविता |row6= वि. सं. २०१५ {{!!}} जन्मोत्सव र मुटुको थोपा {{!!}} ?? |row7= वि. सं. २०१६ {{!!}} [[मृत्युशैयाबाट]] {{!!}} कविता |row8= वि. सं. २०२१ {{!!}} [[चिल्ला पातहरू]] {{!!}} ?? |row9= वि. सं. २०२४ {{!!}} गाईने गीतहरू {{!!}} गीत |row10= वि. सं. २०२४ {{!!}} मनोरञ्जन {{!!}} कविता |row11= वि. सं. २०२४ {{!!}} [[भावना गाङ्गेय]] {{!!}} ?? |row12= वि. सं. २०२४ {{!!}} [[आकाश बोल्छ]] {{!!}} ?? |row13= वि. सं. २०२६ {{!!}} [[छाँगासँग कुरा]] {{!!}} ?? |row14= वि. सं. २०३३ {{!!}} [[लक्ष्मी कविता सङ्ग्रह]] {{!!}} कविता |row15= वि. सं. २०४० {{!!}} [[लक्ष्मी गीत सङ्ग्रह]] {{!!}} गीत }} देवकोटाको कवितायात्राको पूर्वार्द्धकालीन कविता सङ्ग्रहहरूमा ''भिखारी'' कविता सङ्ग्रहलाई, खण्डकाव्यहरूमा ''[[मुनामदन]]'' खण्डकाव्यलाई र महाकाव्यहरूमा '[[शाकुन्तल (महाकाव्य)|शाकुन्तल]]' महाकाव्यलाई प्रतिनिधिकृतिका रूपमा लिन सकिन्छ। उनको उत्तरार्द्धकालीन कवितायात्राका कविता सङ्ग्रहहरूमा ''लक्ष्मी कविता सङ्ग्रह''लाई, खण्डकाव्यहरूमा ''मायाविनी सर्सी'' खण्डकाव्यलाई र महाकाव्यमा ''प्रमिथस'' महाकाव्यलाई प्रतिनिधिकृति मान्न सकिन्छ। यसैगरी देवकोटाका बालकविताहरूका प्रतिनिधिकृतिका रूपमा उनका ''सुनको बिहान'' र ''पुतली'' बालकविता सङ्ग्रहलाई अघि सार्न सकिन्छ भने उनका हाँस्यव्यङ्ग्य कविताहरूको प्रतिनिधित्व उनको 'मनोरञ्जन हाँस्यव्यङ्ग्य कविता सङ्ग्रहले र गीतिकविता वा गीतहरूको प्रतिनिधित्वचाहिँ उनको ''लक्ष्मी गीति सङ्ग्रह''ले गर्दछ। यस सन्दर्भमा देवकोटाका विशुद्ध प्रगतिवादी क्रान्तिकारी कविताहरूको प्रतिनिधित्व गर्ने ''पहाडी पुकार''लाई र उनको रोमान्टिक प्रगतिवादी क्रान्तिकारी गीति नाट्य ''कृषिबाला''लाई पनि उल्लेखनीय छन्। ==देवकोटा:विश्लेषण == [[श्यामदास वैष्णव]] देवकोटाको परिचय यसरी गर्छन् : लक्ष्मीप्रसाद देवकोटा अत्यन्तै प्रतिभाशाली व्यक्ति हुनुहुन्थ्यो। नेपाली साहित्यमा धेरै कुरा रच्नुभयो उहाँले। बाल साहित्यदेखि महाकाव्यसम्म रचना गर्नुभयो। उहाँका कृति विश्वविद्यालयमा राखियो। देशको महाकवि भएर उहाँले धेरै ठाउँमा योगदान दिनु भएको छ, देवकोटाले भाषा अनुवाद संस्थानमा पनि काम गर्नु भएको थियो। त्रिचन्द्र कलेजमा पढाउनु भयो। एकेडेमी बनाउन मद्दत गर्नुभयो। धेरै समयपछि मन्न्री पनि हुनुभयो। कवि सम्मेलनमा नेपालको तर्फबाट देश विदेश जानुहुन्थ्यो। उहाँको मृत्यु भने दुखद् तवरले भयो ।<ref name=setopati>शोभा शर्मा, '''[http://setopati.com/sahityapati/19107 देवकोटाले कोट फुकालेर दिन्थे, पैसा बाँड्थे भन्ने साँचो होइन] {{Webarchive|url=https://web.archive.org/web/20141028180824/http://setopati.com/sahityapati/19107/ |date=2014-10-28 }}''' Setopati.com,प्रकाशित मिति: बिहीबार, कार्तिक ६, २०७१ १४:२२:३३</ref> वैष्णवले थपे -"महाकविले भाषा अनुवादमा काम गरेर पुस्तक लेखेर अनि ट्युसन पढाएर पैसा कमाउनु हुन्थ्योे। तैपनि दुःख भने थियो ।" वैष्णवले भने, 'तर बाटोमा गरीब देखे आफ्नो कोट नै फुकालेर दिन्थे पैसा बाड्दै हिँड्थे भन्छन् नि त्यस्तो भने होइन।"<ref name=setopati /> == तस्वीरहरू == <gallery> |लक्ष्मीप्रसाद देवकोटाको तस्वीर भएको हुलाक टिकट File:Laxmi prasad devkota stamp 2.JPG|देवकोटाको तस्वीर भएको हुलाक टिकट File:Statue of Laxmi Prasad Devkota-TU-9653.jpg|thumb|Statue of Laxmi Prasad Devkota-TU-9653 File:Mahakavi laxmi prasad devkota.jpg|देवकोटाको तस्वीर File:महाकवी, राष्ट्रकवी, र हरिवंश राय बच्चन.webp|thumb|महाकवी, राष्ट्रकवी, र हरिवंश राय बच्चन File:लक्ष्मीप्रसाद देवकोटा.jpg|thumb|लक्ष्मीप्रसाद देवकोटा </gallery> ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} ==यो पनि हेर्नुहोस्== *[[पागल (कविता)]] *[[लक्ष्मीप्रसाद देवकोटा रचनासूची]] ==बाह्य कडीहरू== {{wikiquote|लक्ष्मीप्रसाद देवकोटा}} {{commonscat|Laxmi Prasad Devkota}} # [https://www.nepalilekh.com/Author/Laxmi-Prasad-Devkota/ लक्ष्मीप्रसाद देवकोटाका रचनाहरू (नेपाली लेख डट कम)] {{Webarchive|url=https://web.archive.org/web/20250117043028/https://www.nepalilekh.com/Author/Laxmi-Prasad-Devkota/ |date=2025-01-17 }} # [http://www.youtube.com/v/p0jZ9CanqL0 लक्ष्मीप्रसाद देवकोटाको स्वरमा केही कविताहरू, बीबीसीको कार्यक्रमबाट] # [http://www.spinybabbler.org/literature/personalities/laxmi_prasad_devkota.htm देवकोटाको जीवनी] {{Webarchive|url=https://web.archive.org/web/20051016103642/http://www.spinybabbler.org/literature/personalities/laxmi_prasad_devkota.htm |date=2005-10-16 }} # [http://english.ohmynews.com/articleview/article_view.asp?no=259733&rel_no=1 लक्ष्मीप्रसाद देवकोटा: नेपालका सर्वोत्कृष्ट कवि] {{Webarchive|url=https://web.archive.org/web/20120314032950/http://english.ohmynews.com/articleview/article_view.asp?no=259733&rel_no=1 |date=2012-03-14 }} # [http://literature.wnso.org/2002/munamadan.htm मुना-मदन] # [http://www.newssewa.com/content/devkota.htm देवकोटा भन्थे : कवी काम लाग्ने पागल अरु बेकामका पागल (देवकोटाको अडियो सहित)]{{Dead link|date=September 2023 |bot=InternetArchiveBot |fix-attempted=yes }} #[http://annapurnapost.com/News.aspx/story/46493 लक्ष्मीप्रसाद देवकोटाले मृत्यु भन्दा पहिले आफ्ना आफन्तहरूसँग गरेको कुराकानी] {{Webarchive|url=https://web.archive.org/web/20160403080927/http://www.annapurnapost.com/News.aspx/story/46493 |date=2016-04-03 }} {{लक्ष्मीप्रसाद देवकोटाका कृतिहरू}} {{नेपाली भाषाका साहित्यकारहरू}} [[श्रेणी:नेपाली साहित्यकारहरू]] [[श्रेणी:साझा पुरस्कार विजेताहरू]] [[श्रेणी:सन् १९०९ मा जन्म]] [[श्रेणी:लक्ष्मीप्रसाद देवकोटा| ]] [[श्रेणी:खस जाति]] [[श्रेणी:नेपाली शिक्षकहरू]] 8645i2ihxeyoli9oyxpyyyuuqt6h54s 1361474 1361473 2026-06-12T10:37:43Z Bishaldev100 28807 /* तस्वीरहरू */ 1361474 wikitext text/x-wiki {{विशेष लेख}} {{संक्षिप्त विवरण|नेपाली लेखक}} {{Infobox officeholder | name = लक्ष्मीप्रसाद देवकोटा | honorific_prefix = महाकवि | image = Laxmi Prasad Devkota 3.jpg | caption = लक्ष्मीप्रसाद देवकोटा | alt = | country = [[नेपाल]] | office = [[शिक्षा, विज्ञान तथा प्रविधि मन्त्रालय (नेपाल)|शिक्षा विज्ञान तथा प्रविधि मन्त्री]] | term_start = २०१४ साउन ११ | term_end = २०१५ जेठ २ | primeminister = [[कुँवर इन्द्रजीत सिंह|कुँवर इन्द्रजित सिंह]] | predecessor = | successor = | signature = | birth_date = १९६६ कार्तिक २७ | birth_place = धोविधारा, [[काठमाडौँ]], [[नेपाल अधिराज्य|नेपाल]] | death_date = २०१६ भाद्र २९ | death_place = [[आर्यघाट]] | nationality = [[नेपाली]] | notableworks = | parents = तिलमाधव देवकोटा (पिता)<br>अमरराज्य लक्ष्मी देवी (आमा) | spouse = मानदेवी चालिसे | children = ५ छोरी <br> ४ छोरा | relatives = लोकप्रिया देवी (दिदी) | occupation = साहित्यकार र विद्वान् | image_size = 200px | period = | native_name = | native_name_lang = ne | monarch = [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]] }} '''लक्ष्मीप्रसाद देवकोटा''' एक नेपाली कवि तथा साहित्यकार हुन् । उनको जन्म वि. सं. १९६६ कार्तिक २७ गते '[[लक्ष्मी पूजा|लक्ष्मीपुजा]]'को दिनमा [[काठमाडौँ]]को डिल्लीबजारमा भएको थियो।<ref>{{वेब स्रोत|लेखक=|शीर्षक=लक्ष्मीप्रसाद देवकोटा / परिचय|युआरएल=http://kavitakosh.org/kk/%E0%A4%B2%E0%A4%95%E0%A5%8D%E0%A4%B7%E0%A5%8D%E0%A4%AE%E0%A5%80%E0%A4%AA%E0%A5%8D%E0%A4%B0%E0%A4%B8%E0%A4%BE%E0%A4%A6_%E0%A4%A6%E0%A5%87%E0%A4%B5%E0%A4%95%E0%A5%8B%E0%A4%9F%E0%A4%BE_/_%E0%A4%AA%E0%A4%B0%E0%A4%BF%E0%A4%9A%E0%A4%AF|कार्य=|प्रकाशक=|वेबसाइट=कविताकोश|भाषा=नेपाली)|अभिलेखमिति=|अभिलेखयुआरएल=|मिति=|पहुँचमिति=२० अप्रिल २०२२}}</ref> उनी [[नेपाल|नेपाली]] [[साहित्य]]का [[महाकवि]]का रूपमा सुप्रसिद्ध छन्।<ref>{{वेब स्रोत|लेखक=|शीर्षक=को हुन् लक्ष्मीप्रसाद ? महाकवि देवकोटाको जीवनी|युआरएल=https://lokpati.com/2018/11/5165/|कार्य=|प्रकाशक=लोकपाटी|वेबसाइट=|भाषा=नेपाली)|अभिलेखमिति=|अभिलेखयुआरएल=|मिति=|पहुँचमिति=२० अप्रिल २०२२}}</ref> देवकोटा नेपाली साहित्यका कविता, आख्यान, नाटक र निबन्ध गरी साहित्यका चारवटै विधामा कलम चलाउने बहुमुखी प्रतिभाका धनी मानिन्छन्। उनले [[कविता]] र [[निबन्ध]] विधामा गरेका योगदानहरू उच्च कोटिको मानिन्छ। उनले [[मुनामदन]], [[सुलोचना (महाकाव्य)|सुलोचना]], [[शाकुन्तल (महाकाव्य)|शाकुन्तल]]जस्ता अद्वितीय कृतिहरू लेखेका छन्। विशेष गरी [[मुनामदन]] कृतिका लागि उनी सबैभन्दा प्रख्यात छन्।<ref>{{वेब स्रोत|लेखक=|शीर्षक=मुना र मदनको बिछोडको प्रेम कहानी|युआरएल=https://everestdainik.com/2017/08/106798/?amp_markup=1|कार्य=|प्रकाशक=|वेबसाइट=एभरेष्ट दैनिक|भाषा=नेपाली)|अभिलेखमिति=|अभिलेखयुआरएल=|मिति=|पहुँचमिति=२० अप्रिल २०२२}}</ref><ref>{{वेब स्रोत|लेखक=कृष्णप्रसाद कोइराला |शीर्षक=समीक्षा-मुनामदन खण्डकाव्य|युआरएल=https://sahityasangraha.com/2017/07/28/%E0%A4%AE%E0%A5%81%E0%A4%A8%E0%A4%BE%E0%A4%AE%E0%A4%A6%E0%A4%A8-%E0%A4%96%E0%A4%A3%E0%A5%8D%E0%A4%A1%E0%A4%95%E0%A4%BE%E0%A4%B5%E0%A5%8D%E0%A4%AF/|कार्य=|प्रकाशक=|वेबसाइट=|भाषा=नेपाली)|अभिलेखमिति=|अभिलेखयुआरएल=|मिति=|पहुँचमिति=२० अप्रिल २०२२}}</ref> उनको निधन वि.सं. २०१६ भाद्र २९ मा पचास वर्षकै उमेरमा नै भएको थियो। == प्रारम्भिक जीवन र शिक्षा == देवकोटा पण्डित तीलमाधव र अमर राज्यलक्ष्मी देवीका तेस्रो छोरा थिए। उनी डिल्लीबजार, धोबीधारा, [[काठमाडौँ]]मा [[तिहार]]को [[लक्ष्मी पूजा]]का दिन जन्मिएका थिए। विक्रम सम्वत् १९६६ साल कार्तिक २७ गते गाई तिहार/औँशी [[लक्ष्मी पूजा|लक्ष्मीपूजा]]का दिन जन्मेका हुनाले यिनको नाम लक्ष्मीप्रसाद राखिएको हो, तर उनको न्वारानको नाउँ तीर्थमाधव देवकोटा हो। <ref>{{Cite web |last=पराजुली |first=गोपाल |date=2022-07-27 |title=महाकवि लक्ष्मीप्रसाद देवकोटा |url=https://www.gorkhapatra.org.np/mag/muna.detail.php?article_id=223&cat_id=17 |url-status=dead |archive-url=https://web.archive.org/web/20131206120800/https://www.gorkhapatra.org.np/mag/muna.detail.php?article_id=223&cat_id=17 |archive-date=2013-12-06 |access-date=2022-07-27 |website=गोरखापत्र |language=नेपाली }} {{Webarchive|url=https://web.archive.org/web/20131206120800/https://www.gorkhapatra.org.np/mag/muna.detail.php?article_id=223&cat_id=17 |date=2013-12-06 }}</ref><ref>{{Cite web |last=Sharma |first=Kumar |date=2014-10-23 |title=Mahakavi Devkota: The legend lives on |url=https://kathmandupost.com/miscellaneous/2014/10/23/mahakavi-devkota-the-legend-lives-on |url-status=live |access-date=2022-07-27 |website=The Kathmandu Post|language=अङ्ग्रेजी}}</ref>देवकोटाका बुबा संस्कृतका विद्वान् थिए। त्यसैले उनले आफ्नो आधारभूत शिक्षा बुबाको संरक्षकत्वमा प्राप्त गरेका थिए। उनले [[दरबार हाई स्कुल]]मा औपचारिक शिक्षाको सुरुवात गरेका थिए। उनले संस्कृत व्याकरण र अङ्ग्रेजी दुवैको अध्ययन गरेका थिए। देवकोटा दरबार हाई स्कुलमा नै आफ्ना साथीहरूलाई कविता सुनाउने गर्थे । उनका प्रायः साथीहरूले ती कविता देवकोटाले नै लेखेका हुन् भनेर स्वीकार्दैनथे । यसै क्रममा एक दिन सबै विद्यार्थी मिलेर यिनको बेइज्जत गर्ने हिसाबले कविता लेख्ने परीक्षा लिए । यिनले पनि सबै विद्यार्थीमाझ कविता लेखे अनि त्यसै घडी शिक्षकहरूले उनलाई ‘कोपिलाउँदो कवि’को दर्जा दिए। सन् १९२५ मा देवकोटा [[त्रि-चन्द्र कलेज]]मा विज्ञान विषयमा भर्ना भए। विज्ञानमा प्रमाणपत्र तहको अध्ययन पूरा गरेपछि उनी मानविकी सङ्कायमा सरेका थिए। सन् १९२९ मा आफ्नो स्नातक तहको अध्ययन पूरा गरेपछि, सन् १९३१ मा छात्रवृत्ति लिएर अङ्ग्रेजीमा स्नातकोत्तर पढ्ने आशामा उनी भारतको पटना गएका थिए। अङ्ग्रेजी विषयमा स्थान नपाएपछि उनले कानून पढेका थिए। आफ्नो परिवारको आर्थिक अवस्थाले गर्दा आफ्नो स्नातकोत्तर पूरा गर्ने उनको इच्छा अपूर्ण बनेको थियो।<ref>{{Cite web |last=लम्साल |first=युव नाथ |date=2013-12-06 |title=महाकवि: लक्ष्मीप्रसाद देवकोटा |url=https://www.gorkhapatra.org.np/gopa.detail.php?article_id=20008&cat_id=10 |url-status= |archive-url=https://web.archive.org/web/20131206120225/https://www.gorkhapatra.org.np/gopa.detail.php?article_id=20008&cat_id=10 |archive-date=2018-04-25 |access-date=2013-12-06 |website=गोरखापत्र }} {{Webarchive|url=https://web.archive.org/web/20131206120225/https://www.gorkhapatra.org.np/gopa.detail.php?article_id=20008&cat_id=10 |date=2013-12-06 }}</ref> देवकोटा जन्मेदेखि नै उनका घरमा अनेक कष्टहरूको प्रवेश भइरह्यो। उनको घरको व्यवस्थापकीय ढाँचा पनि अत्यन्तै दयनीय थियो। साथै उनको घरले गरिबीको रेखाबाट उम्किन पनि सकेको थिएन। त्यसैले उनी सानैमा भन्थे, ‘म अङ्ग्रेजी पढ्छु र धेरै पढेपछि ट्युसन पढाएर पैसा कमाउँछु। देवकोटाले बाल्यकालमा नै अमरकोश घोकेका थिए र स्तोत्रमाला पढेका थिए। उनी सानैदेखि आफ्ना बुबाको कविता साफी गर्थे। आफ्ना बुबाको कविता सार्दासार्दै उनी भित्र पनि साहित्यको रस बस्न थालेको थियो। उनलाई उनका बुबाले पण्डित बनाउन खोजेका थिए। == साहित्यिक यात्रा== देवकोटा बहुमुखी प्रतिभका धनी एवम् असाधारण लेखक थिए। दस वर्षको उमेर देखि नै कविता लेखनको सुरुवात गरेका उनको छोटो जीवनमा उनले नछोएको साहित्यको कुनै विधा छैन। उनले महाकाव्य, खण्डकाव्य, लामा वर्णनात्मक कविताहरू, निबन्धहरू, कथाहरू, नाटक, गीतहरू र समालोचनाहरू लेखेका छन्। कविता पढेजस्तै अनुभव हुने देवकोटाका निबन्धहरू शैली र विषयवस्तुका लागि एकदमै प्रशंसायोग्य छन्। देवकोटाले आधुनिक नेपाली भाषाको रोमान्टिक आन्दोलन सुरु गरेर नेपाली साहित्यमा योगदान दिएका थिए। नेपाली साहित्यमा [[महाकाव्य]] लेखन सुरु गर्ने उनी नेपालमा जन्मिएका दोस्रो लेखक थिए। साहित्यमा भाषाको नवीन प्रयोगसँगै नेपाली कविता देवकोटाको समयमा नयाँ उचाईमा पुगेको थियो। त्यतिबेला नेपाली साहित्यिक दृश्यमाथि प्रभुत्व जमाएको संस्कृत परम्परा त्यागेर [[नेवारी भाषा|नेपाल भाषा]]को ''जि वया ला लछि मदुनी''बाट प्रेरित भएर उनले [[मुनामदन]] (विसं १९९३) लेखेका थिए। लोकप्रिय झ्याउरे छन्द(भाका)मा उनले लामो आख्यानात्मक कविता लेखेका थिए। मुनामदन नेपाली साहित्यको इतिहासमै निकै उत्कृष्ट पुस्तक हो। ७६औँ एकेडेमी पुरस्कारमा सर्वोत्कृष्ट विदेशी भाषाको चलचित्रका लागि नेपालको आधिकारिक प्रवेश भएको सन् २००३ को चलचित्र मुनामदन यही खण्डकाव्यमा आधारित थियो। यो कार्यले त्यतिबेलाका देशका शासकहरू अर्थात् राणाहरूबाट तत्कालै मान्यता पाएको थियो। 'मुनामदन'मा मुना आफ्ना पति यात्रारत व्यापारी मदनको कथा सुनाउँछिन्। श्रीमती मुनालाई छोडेर केही पैसा कमाउनका लागि ऊ तिब्बत प्रस्थान गर्छ। खण्डकाव्यमा यात्राको विषयगत कष्ट, वियोगको शोक, तिर्सनाको चञ्चलता र मृत्युको पीडाको वर्णन गरिएको छ। देवकोटाद्वारा लिखित वियोगान्त खण्डकाव्य [[मुनामदन]] देवकोटाको मृत्युको पाँच दशक पछिसम्म पनि साझा प्रकाशनद्वारा अत्यधिक बिक्री हुने कृतिमा पर्दछ। ´मुनामदन` नेपाली जनजीवनमा भिजेको पहिलो नेपाली कृति हो। <ref>{{Cite web |last=गौतम |first=प्रभाकर |date=2019-06-29 |title=नेवारी गीतिकाव्य ‘जि वया ला लछि मदुनी’ बाट प्रभावित थियो देवकोटाको मुनामदन |url=https://www.setopati.com/art/art-activity/183642/ |url-status=live |access-date=2022-07-27 |website=सेतोपाटी |language=नेपाली }} {{Webarchive|url=https://web.archive.org/web/20220728021101/https://www.setopati.com/art/art-activity/183642/ |date=2022-07-28 }}</ref> ''जि वया ल लछी मदुनी'' एक नेवार व्यापारी, उनकी आमा र श्रीमतीमा आधारित एउटा दुखद गीत हो। व्यापारीले कामका लागि काठमाडौँ छाड्छ र तिब्बत तिर प्रस्थान गर्दछ। यो गीत श्रीमतीले सासूलाई उनको श्रीमानलाई जान नदिन बिन्ती गर्दा सुरु हुन्छ। काठमाडौँमा हुर्केका देवकोटाले स्थानीयले गाएको यो गीत फल्चामा सुनेका थिए। यो गीतबाट उनी अत्यन्तै मोहित भए र नेपाली भाषामा पुन: लेख्ने निधो गरेका थिए। राणा शासकहरूले नेवारी व्यापार, भाषा र साहित्यमाथि प्रतिबन्ध लगाउने भएकाले उनले मूल गीतमा जस्तै नेवार व्यापारीबाट मुख्य पात्रपरिवर्तन गरी क्षत्रिय (योद्धा वर्ग) चरित्रमा परिवर्तन गरेका थिए। क्षेत्री मानिसहरूले ती दिनहरूमा आफ्नो जीविकाको लागि व्यापार नगर्ने भए तापनि राणा शासकहरूलाई लोभ्याउन तिनले यसलाई त्यस्तो चित्रण गर्नुपरेको थियो। यस खण्डकाव्यबाट सबैभन्दा प्रसिद्ध र बारम्बार उद्धृत गरिएको श्लोक मध्ये एक यस्तो छ: <poem> "क्षेत्रीको छोरो यो पाउ छुन्छ, घिनले छुँदैन मानिस ठूलो दिलले हुन्छ जातले हुँदैन !" </poem> उत्कृष्ट कृतिको रूपमा मुनामदन नेपाली साहित्यका सामान्य पाठकमाझ निकै लोकप्रिय रहँदै आएको छ।<ref>{{Cite web |last=Acharya |first=Tulasi |date=2022-04-16 |title=The Nepali literary environment |url=https://kathmandupost.com/columns/2022/04/16/the-nepali-literary-environment |url-status=live |archive-url=https://web.archive.org/web/20220417105143/https://kathmandupost.com/columns/2022/04/16/the-nepali-literary-environment |archive-date=2022-04-17 |access-date=2022-07-27 |website=The Kathmandu Post |language=अङ्ग्रेजी}}</ref> यो वि. संं. १९९३ देखिको सबैभन्दा लोकप्रिय नेपाली पुस्तक रहेको छ भने यसलाई चिनियाँ भाषामा समेत अनुवाद गरिएको थियो। यसलाई चीनले राम्रोसँग ग्रहण गरेपछि यसलाई सफल ठानिएको थियो।<ref>{{Cite web |last=Mahat |first=Sunny |date=2019-01-04 |title=‘Muna Madan’ in Mandarin |url=https://theannapurnaexpress.com/news/books-in-translation-1067 |url-status=live |archive-url=https://web.archive.org/web/20220509182715/https://theannapurnaexpress.com/news/books-in-translation-1067 |archive-date=2022-05-09 |access-date=2022-07-28 |website=The Annapurna Express |language=अङ्ग्रेजी}}</ref> देवकोटाले सन् १९३९ मा मानसिक शरणमा रहेको पाँच महिने प्रवासबाट प्रेरित भएर मुक्तक कविता 'पागल' लेखेका थिए। यो कविता उनको असामान्य मानसिक क्षमतासँग सम्बन्धित छ र नेपाली भाषाका उत्कृष्ट कविताहरू मध्ये एक मानिन्छ। <poem> "जरुर साथी म पागल ! यस्तै छ मेरो हाल । म शब्दलाई देख्दछु ! दृश्यलाई सुन्दछु ! बासनालाई संवाद लिन्छु । आकाशभन्दा पातालका कुरालाई छुन्छु । ती कुरा, जसको अस्तित्व लोक मान्दैन जसको आकार संसार जान्दैन !...." </poem> [[File:Laxmi Prasad Devkota.jpg|alt=Laxmi Prasad Devkota|thumb|महाकवि देवकोटा]] देवकोटासँग धेरै छोटो समयमा साहित्यिक जटिलता र दार्शनिक घनत्वसहितलामो महाकाव्य र कविता रचना गर्ने क्षमता थियो जसअन्तर्गत उनले [[शाकुन्तल (महाकाव्य)|शाकुन्तल]] महाकाव्यको रचना गरेका थिए। उनको पहिलो महाकाव्य कविता र नेपाली आधुनिक महाकाव्यको जगतमा उनले तीन महिनामै यसको लेखन कार्य सकाएका थिए। सन् १९४५ मा प्रकाशित शाकुन्तल [[कालिदास]]को प्रसिद्ध संस्कृत नाटक [[अभिज्ञानशाकुन्तलम्]]मा आधारित छ। शाकुन्तलले देवकोटाको संस्कृत ज्ञान र शव्दकोशमा निपुणताको प्रदर्शन गर्दछ, जुन उनले मुख्यतया नेपालीमा रुपान्तरण गर्दा भारी मात्रामा गहन शब्दहरूको समावेश गरेका थिए। देवकोटाका दिवंगत विद्वान तथा अनुवादक डेभिड रुबिनका अनुसार शाकुन्तलले सबैभन्दा धेरै उपलब्धि हासिल गरेको छ। "यो, निसन्देहः एक उल्लेखनीय कृति, आधुनिक दृष्टिकोणसँग शास्त्रीय परम्पराका विभिन्न तत्वहरूलाई मिलाएर, ब्रह्माण्डीय लाक्षणिक, [[कालिदास]]को पार्थिव प्रेमको रोमान्टिक हाँस्यसँग मेल खान्छ, जसले कामुक र पवित्र प्रेमको सङ्गालोद्वारा मुक्तिको सङ्केत दिन्छ। देवकोटाले विभिन्न परम्परागत र गैरपरम्परागत विधामा स्थापित लघुगीतकविताका थुप्रै सङ्ग्रह पनि प्रकाशित गरेका थिए। उनका अधिकांश कविताले [[विलियम वोर्डस्वर्थ]] र कोलेरिज जस्ता अङ्ग्रेजी रोमान्टिक कविहरूको प्रभाव देखाउँछन्। कविता सङ्ग्रह ''[[भिखरी (कवितासङ्ग्राह)|भिखारी]]''मा रहेको शीर्षक कविता वर्ड्सवर्गको "द ओल्ड कम्बरल्यान्ड बेगर" को सम्झना हो। यस कवितामा देवकोटाले मानव प्रेम र भौतिक सुखसुविधाबाट बञ्चित भएर कठोर गरिबी र विध्वंशमा आफ्नो बाटो हिँडेको भिखारीको वर्णन गरेका छन्। अर्कोतर्फ भिखारीलाई दुःखकष्ट र दन्किरहेको अवस्थामा राखिएको अनुकम्पाको स्रोतको रूपमा पनि लिइन्छ। देवकोटाले भिखारीलाई दिव्यसँग दया र समानुभूतिको परम फन्दाको रूपमा जोडेका छन्: <poem> "कालो बादलबाट खसेको अन्धकारमा भित्र पसेको, ईश्वर हो कि भिखारी ? बोल्दछ ईश्वर हृदय घुसेका, घर, घर आँगन चारी बोल्दछ, आर्तध्वनिमा बोल्दछ करूणामृत दिल भारी ।...." </poem> देवकोटाका थुप्रै कविताहरू मानव र प्राकृतिक संसारका सांसारिक तत्त्वहरूमा केन्द्रित छन्। वन, किसान, बादल जस्ता उनका कविताका शीर्षकहरूले उनले विश्वका साझा र सम्बत पक्षहरूमा आफ्नो काव्यात्मक प्रेरणाको खोजी गरेको देखाउँछन्। उनका अधिकांश कविताहरूमा मानवताप्रतिको तिनको गहिरो विश्वासले गहिरो छाप पारेको छ। उदाहरणका लागि, वन भन्ने कवितामा वक्ताले व्यक्तिगत रूपले मात्र दिन सकिने सबै प्रकारका सान्त्वना तथा सान्त्वनाहरूलाई तिरस्कार गर्दै एकपछि अर्को केरकारहरू गर्छन्। यस कविताको अन्तमा वक्ताको मानवतावादी झुकावलाई प्रकाश पार्ने निम्न कवितांश प्रस्तुत गर्दछ: <poem> "दोस्त कहाँ छन्? साथ छ को को? घर हो तिम्रो कुन देश? जान्छौ कुन पुर भवन मुसाफिर, ल्यायौ कुन सन्देश? दोस्त मेरो शुभ उद्योगी, साथ छ साहस बेश । विश्व सबै घर, हृदय-पुरीतिर ल्याउँछु सेवा सन्देश ॥" </poem> देवकोटासँग कविताहरू एकदमै चाँडो लेख्‍ने अद्वितीय प्रतिभा थियो। उनले [[शाकुन्तल (महाकाव्य)]] तीन महिनामा, [[सुलोचना (महाकाव्य)]] दश दिनमा र [[कुञ्जिनी]] खण्डकाव्य एकै रातमा लेखे। उनले नेपाली साहित्यलाई नयाँ उचाइमा पुर्‍याए। प्रचलित लोक भाका अर्थात् झ्याउरे छन्दमा लेखिएको कृति मुनामदनले नेपाली साहित्यमा संस्कृतको प्रभावको अन्त्य गरेको थियो। "पागल" कविता उनको अर्को महान सिर्जना हो; जुन कवितामा उनले आफूलाई पागल भन्नेहरूलाई नै कवितात्मक शैलीमा जवाफ दिएका छन्| <ref>नेपाली साहित्य शृङ्खला, ''भाग २, प्रा. डा. बासुदेव त्रिपाठी''</ref> नेपाली भाषासाहित्यमा देवकोटा रूमानी प्रवृत्तिलेखन स्वच्छन्दवादका श्रीगणेश भए। साथै नेपाली भाषासाहित्यलाई अङ्ग्रेजी भाषासाहित्यमा अनुवाद गरेर सर्वप्रथम पश्चिमी मुलुकमा पुर्‍याउने काम पनि देवकोटाबाट नै भएको थियो। भारतीय महापण्डित डा [[राहुल साङ्कृत्यायन]]ले भनेका थिए, ‘मैले देवकोटालाई बुद्धपछिको सबैभन्दा ठूलो मानवअवतारका रूपमा लिएको छु।’ साङ्कृत्यायनले देवकोटालाई भारतका जल्दाबल्दा तीन कवि जयशङ्कर प्रसाद, सुमित्रानन्दन पन्त र सूर्यकान्त त्रिपाठी निराला बराबर एक जना देवकोटा हुन् भनेका थिए। <ref>महाकवी लक्ष्मी प्रसाद देवकोटा जीवनी (१९०९-१९५९)</ref> देवकोटा चौध भाषा बुझ्थे। उनी द्वारा नौ भाषामा लेखिएका कविताहरू ´शारदा` मासिक मार्फत जनमाझ पनि आए। देवकोटालाई काव्यसागरका जलदेवता भने पनि हुन्थ। उनी उठ्ता, बस्ता, हिँड्दा, सुत्दा, खाँदा वा आफ्ना चेतन र अचेतनका कुनै पनि पलमा काव्यभन्दा बाहिर हुँदैन थिए। बिहान आँखा उघारेदेखि राति आँखा चिम्लेपछिको स्वप्नसंसारमा पनि उनी काव्यसंसारमा नै यात्रा गर्थे। उनको बाँचुन्जेलको साथी एउटा ´कविता` थियो र अर्को ´चुरोट` थियो। लेखेका बेला उनी आफ्नै पाण्डुलिपि बालेर चुरोट सल्काएको र त्यसैले सिँगान पुछेको पनि चाल पाउँदैन थिए। == राजनीति == [[चित्र:Laxmi Prasad Devkota Stamp.jpg|alt=Commemorative stamp of Devkota|thumb|247x247px| हुलाक टिकटमा देवकोटाक‍ तस्वीर]] लक्ष्मीप्रसाद देवकोटा कुनै पनि स्थापित राजनीतिक दलभित्र सक्रिय थिएनन् तर उनका कविताले निरन्तर रूपमा उत्पीडित राणा वंशका विरुद्ध विद्रोहको रवैयालाई मूर्तरूप दिएको थियो। वाराणसीमा स्वनिर्वासन हुँदा उनले [[नेपाली काङ्ग्रेस|नेपाली काङ्ग्रेस]]को युगवाणी पत्रपत्रिकाको सम्पादक भएर काम गर्न थालेका थिए। राणा सरकारले नेपालमा आफ्नो सबै सम्पत्ति जफत गरेको थियो। === लाइब्रेरी पर्व === {{मुख्य|लाइब्रेरी पर्व}} [[भीम शमशेर जङ्गबहादुर राणा|भीमशमशेर]]ले देशमा नेपाली, हिन्दी, अङ्ग्रेजी र नेवारीमा भाषाको उन्नति गर्न भनेर इस्तिहार जारी गरे । यो खबर पाएर काठमाडौंका केही युवाहरूले पठन संस्कृतिको विकास तथा देशविदेशका कुरा थाहा पाउन एउटा पुस्तकालयको आवश्यकता महसुस गरे । त्यस्तो पुस्तकालय महेन्द्रबहालमा राख्ने योजनासहित ४५ जना युवाहरूले श्री ३ भीम शम्शेरसमक्ष निवेदन पेस गर्न हस्ताक्षर अभियान चलाए । हस्ताक्षर गराउने मुख्य जिम्मा बैकुण्ठप्रसाद लाकौलले पाएका थिए । केही समयपश्चात हस्ताक्षर संकलन समेत भईवरी दरबारमा पत्र बुझाइयो । तर हस्ताक्षर नगर्ने रामचन्द्र अधिकारी नामक अर्का युवाले हस्ताक्षरकर्ता युवाहरूको अभियान राजनीतिक उद्देश्यको भएको र उनीहरूले श्री ३ को गाथगादी ताकेका छन् भन्ने उजुरी दरबारमा चढाए । यसरी सरस्वती गुठी नामक संस्था स्थापना गरी त्यसमार्फत् पुस्तकालय खोल्ने कार्यलाई राजनीतिक आवरणको आरोप लागेपछि दरबारले पत्रका हस्ताक्षरकर्ता सबैलाई पक्राउ गर्न उर्दी जारी गर्‍यो । अधिकांश हस्ताक्षरकर्ताहरूलाई पक्राउ गरी बयान लिने क्रममा उक्त घटनालाई 'लाइब्रेरी पर्व' भनी मुद्दा जाहेर भयो । बि‍. सं १९८७ साल वैशाख १६ र १७ गते दुई दिन गरी पुस्तकालय खोल्ने अभियानका युवाहरूलाई पक्राउ गरियो । त्यसरी पक्राउ परेका युवाहरूलाई दरबारबाट बिभिन्न सजाय तोकियो । ती मध्ये उमेश शाहलाई देश निकाला र मैनाबहादुर, खड्गमान, रंगनाथ आदिलाई जन्मकैदको सजाय सुनाइएको थियो । [[लक्ष्मीप्रसाद देवकोटा]], [[सिद्धिचरण श्रेष्ठ]], [[कृष्णप्रसाद कोइराला]]लगायतलाई रु. १०० जरिवाना र अबका १२ वर्ष जनस्तरका कुनै कार्य गर्ने छैन भन्ने कागज गराई छोडिएको थियो । राज खानदानका भएर पनि दुनियाँका छोराहरूका साथ हिँडेको भनी जितेन्द्र बहादुर शाह र पद्म शाहलाई जनही रु. १००० जरिवाना गरिएको थियो । पुस्तकालय खोल्न पाऊँ भनी पत्रमा हस्ताक्षर गर्ने ४५ जना युवाहरूमा महाकवि लक्ष्मीप्रसाद देवकोटा, सिद्धिचरण श्रेष्ठ, कृष्णप्रसाद कोइराला, [[चित्तधर हृदय]], योगवीरसिंह कंसाकार, वैकुण्ठप्रसाद लाकौल, [[तुलसीमेहर श्रेष्ठ|तुलसी मेहर]], शंकरप्रसाद नेपाल, [[महेन्द्र विक्रम शाह|महेन्द्रविक्रम शाह]], [[शङ्करदेव पन्त|शंकरदेव पन्त]]जस्ता साहित्य, भाषा, शिक्षा तथा सामाजिक सांस्कृतिक क्षेत्रमा प्रसिद्ध युवाहरू थिए ।<ref>{{Cite news|url=https://ekantipur.com/bibidha/2023/04/29/168267052220824323.html|title='लाइब्रेरी पर्व'को महत्त्व र राष्ट्रिय लेखक दिवसको औचित्य|last=नेपाल|first=रत्नमणि|date=वैशाख १६, २०८०|work=कान्तिपुर}}</ref> सार्वजनिक पुस्तकालय खोल्छु भन्नेलाई [[भीम शमशेर जङ्गबहादुर राणा|भीमशमशेर]]ले जेलमा कोचे। यस्तो धोखाधडीका कारण पनि उनी इतिहासमा बदनाम छन्। [[लाइब्रेरी पर्व]]ले भीमशमशेरको अनुदार छवि प्रस्तुत गर्छ। ===सल्लाहकार समिति सदस्य=== वि.सं. २००७ सालको क्रान्तिमार्फत प्रजातन्त्रको परिचय गराएपछि देवकोटालाई राजा त्रिभुवनद्वारा वि.सं. २००८ मा नेपाल सल्लाहकार समितको समूहको सदस्यमा नियुक्त गरिएको थियो। उक्त सल्लाहकार सभाको अध्यक्षका लागि नेपाली कांग्रेसका महामन्त्री [[कृष्णप्रसाद भट्टराई]] र लक्ष्मीप्रसाद देवकोटाले उम्मेदवारी दिएका थिए । मतदानमा भट्टराईले ४० र देवकोटाले १४ मत पाए र भट्टराई अध्यक्ष (स्पिकर) चुनिए। <ref>{{Cite journal |last=Nepal |first=जगत Jagat नेपाल |last2=Kafle |first2=डोलराज Dolaraj काफ्ले |last3=Khatiwada |first3=महा प्रसाद Maha Prasad खतिवडा |date=2025-01-06 |title=प्रजातान्त्रिक नेपालको पहिलो संसद, सल्लाहकार सभा र मिडिया कभरेज |url=https://www.nepjol.info/index.php/vaikharivani/article/view/70312/55792 |journal=Vaikharivani |language=en |volume=2 |issue=1 |pages=69–78 |doi=10.3126/vaikharivani.v2i1.70312 |issn=3021-9833}}</ref> उक्त सल्लाहकार सभा २००९ भदौ १९ मा अन्त्य भयो । [[त्रिभुवन वीरविक्रम शाह|राजा त्रिभुवन]]को पालामा बुद्धिजीवी वर्गको प्रतिनिधिका रूपमा राजा त्रिभुवनबाट ‘सल्लाहकार सभा’मा उनी पुनः मनोनीत भएका थिए। सल्लाहकार सभा गठन हुँदा देवकोटालाई विपक्षी नेता बनाइएको थियो। सो सल्लाहकार सभाको दोस्रो अधिवेशनमा [[मातृकाप्रसाद कोइराला]]द्वारा प्रस्तुत बजेटमाथि विपक्षी दलका नेताका हैसियतले गरेको चर्को भाषणकै कारण सरकार विघटित हुनपुगेको थियो।<ref>[https://echitwanpost.com/92148/2019110211/44/40/ महाकवि देवकोटाको मूलदर्शन : अध्यात्म (व्यक्तित्व/कृतित्व चर्चा)]</ref> [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]]ले पनि देवकोटाको सो पदलाई निरन्तरता दिएका थिए। देवकोटा [[त्रिभुवन विश्वविद्यालय]]को स्थापनासँगै सो विश्वविद्यालयको समिति सदस्यमा मनोनीत भएका थिए। त्यसपछि उनैको हस्ताक्षरमा विश्वविद्यालयको रूपरेखा तयार भएको थियो। उनी पछि नेपाल प्रज्ञाप्रतिष्ठानका सदस्य पनि भएका थिए। === शिक्षा मन्त्री === [[कुँवर इन्द्रजीत सिंह|कुँवर इन्द्रजित सिंह]]को [[कुँवर इन्द्रजीत सिंह मन्त्रिपरिषद्|मन्त्रिपरिषद्मा]] देवकोटा शिक्षा, स्वायत्तशासन मन्त्री थिए । <ref>[http://rajpatra.dop.gov.np/welcome/book/?ref=1104०१४ साल श्रावण ११ गतेको नेपाल गजेट]</ref> शिक्षामन्त्री भएपनि देवकोटालाई शिक्षा मन्त्रालय कहाँ छ भन्ने थाहा थिएन र उनलाई [[सत्यमोहन जोशी]]ले गाडीमा मन्त्रालय पुर्‍याएका थिए। शिक्षामन्त्री छँदा उनले त्रिभुवन विश्वविद्यालय र प्रज्ञाप्रतिष्ठानको स्थापना गर्न महत्त्वपूर्ण योगदान गरेका थिए। [[कुँवर इन्द्रजीत सिंह मन्त्रिपरिषद्|केआई सिंहको प्रधानमन्त्रित्वमा गठित मन्त्रिपरिषद्मा]] उनी शिक्षा तथा स्वायत्त शासनमन्त्री पनि बनेका थिए। ११० दिनसम्म मन्त्री भएका बेला उनले नेपाल राष्ट्रभरिका विद्यालय र कलेजहरूमा नेपाली भाषामा पढाइ हुने व्यवस्था मिलाएका थिए। == तास्केन्त सम्मेलनमा सहभागी == [[चित्र:Madhav Prasad Ghimire with Laxmi Prasad Devkota 2.jpg|alt=Devkota with poet Madhav Prasad Ghimire|thumb|338x338px|महाकवि देवकोटा (दायाँ) [[माधवप्रसाद घिमिरे (साहित्यकार)|माधवप्रसाद घिमिरे]]सँग]] सन् १९५८ को अक्टोबरमा तत्कालीन सोभियत गणतन्त्र [[उज्बेकिस्तान]]को राजधानी [[तास्केन्त]]मा भएको अफ्रिकी–एसियाली लेखक सम्मेलनमा देवकोटाले नेपाली मण्डलको नेतृत्व गरेका थिए। त्यतिबेला [[नेपाली काङ्ग्रेस]]को सरकार थियो। उनले राजासँग स्वीकृति नलिई सरकारसँग स्वीकृति लिएका थिए। त्यतिबेला [[भारत]]को [[नयाँ दिल्ली]]बाट [[प्रवेशाज्ञा|भिसा]] लिँदै उनी र [[माधवप्रसाद घिमिरे (साहित्यकार)|माधव प्रसाद घिमिरे]] तास्केन्त पुगेका थिए। देवकोटाले राजासँग स्वीकृति नलिएर राजाको अनादार गरे भनेर उनको विरोध भएको थियो। राजा [[नेपाल प्रज्ञा प्रतिष्ठान|प्रज्ञा प्रतिष्ठान]]को कुलपति थिए। देवकोटा कम्युनिस्ट भयो भनेर उनको विषयमा [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]]लाई कुरा लगाउने काम गरिएको थियो। उनले [[नेपाली भाषा]] साहित्यको विषयमा त्यहाँ बुलन्द भाषण गरेका थिए। तर यता देशको नाम बदनाम गर्‍यो भनेर राजालाई उचाल्ने काम भएको थियो। [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]]ले पनि उनको तीन महिनाको तलब जरिवानाबापत रोक्का गरिदिएका थिए। यस घटनाले उनी निराश बनेका थिए। पछि [[श्यामदास वैष्णव]]सँग आफ्नो निराशा व्यक्त गर्दै भनेका थिए "धेरै बाँचियो ! बाँच्न पुग्यो।" <ref name=":1">श्यामदास वैष्णव ; आफू जलेर उज्यालो दिने मैन ; नागरिक दैनिक २०६९ कार्तिक २५</ref> देवकोटा नेपालबाट [[प्रवेशाज्ञा]] र [[राहदानी]] नबनाई तास्केन्त गएका थिए। त्यसका निम्ति उनलाई मन्त्रिपरिषद्का अध्यक्ष [[सुवर्ण शमशेर राणा|सुवर्णशमशेर]]देखि [[नेपाल प्रज्ञा प्रतिष्ठान|शाही नेपाल प्रज्ञाप्रतिष्ठान]]का उपकुलपति [[बालचन्द्र शर्मा]]सम्मले हरियो झण्डा देखाएर प्रेरित गरेका थिए। तर पछि तिनै व्यक्तिहरूको सिफारिसमा नै देवकोटाले प्रज्ञाप्रतिष्ठानबाट पाउने पारिश्रमिक रोक्का गरिएको थियो। तर पछि त्यसको रहस्य खुलेपछि एक महिनाको तलब जरिमाना गरेर [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]]ले उनको पारिश्रमिक निकासा गरिदिएका थिए।<ref name=":1" /> == व्यक्तिगत जीवन == देवकोटाको १५ वर्षको उमेरमा मनदेवी चालिसेसँग विवाह भएको थियो। वि.सं. १९८५ मा उनको पहिलो सन्तान स्वरूप छोरी सावित्री र वि.सं. १९८९ मा जेठो छोराको रुपमा प्रकाशको जन्म भएको थियो। माहिला छोरा कृष्णप्रसाद देवकोटाको जन्म वि.सं. १९९३ मा भएको थियो। देवकोटाका छोरा पदम देवकोटा कवि तथा लेखक हुन्। उनी [[त्रिभुवन विश्वविद्यालय]]को अङ्ग्रेजी विभाग, काठमाडौंमा धेरै वर्ष प्राध्यापकको रूपमा कार्यरत थिए।<ref>{{Cite web |date=2022-02-01 |title=A Concocted Emotion Is not Poetry: Padma Devkota |url=https://thegorkhatimes.com/2022/02/01/a-concocted-emotion-is-not-poetry-padma-devkota/ |access-date=2022-05-15 |website=The Gorkha Times |language=अङ्ग्रेजी}}</ref> देवकोटाले कानुनमा स्नातको उपाधि हासिल गरेपछि उनी आफ्नो घर फर्के; जहाँ उनले विभिन्न व्यक्तिगत सङ्कटहरू भोग्नु परेको थियो। दुई वर्ष भित्रै उनका बुवा, आमा र दुई वर्षे छोरीको मृत्यु भएको थियो। ती वियोगान्त घटनाहरूले उनलाई मर्माहत तुल्याउँदा यसैबाट उनीमा चुरोटको लत बसेको थियो। पछिल्ला वर्षहरूमा उनका कलिला छोराहरू प्रकाश र कृष्णको असामयिक मृत्युले उनी झन् मर्माहीत भएका थिए र यसले उनको मस्तिष्कलाई समेत चोट पुर्‍याएको थियो। मानसिक समस्याहरूबाट गुज्रिरहेका देवकोटाले पाँच महिना [[भारत]]को राँचीमा अवस्थित मानसिक अस्पतालमा समेत समय बिताएका थिए। पछि आफ्नो जीवनमा आर्थिक ऋण र छोरीहरूको विवाह र दाइजोमा खर्च गर्न असमर्थ भएको कारण उनले एक पटक आफ्नी श्रीमतीलाई यसो भनेका थिए, "आज राती हामी बच्चाहरूलाई समाज र युवाको हेरचाहमा त्यागौँ र सुत्ने समयमा यस संसारलाई त्यागौँ, पोटासियम साइनाइड वा मोर्फिन वा यस्तै केही गरौँँ"। == अन्तिम वर्ष र मृत्यु == [[चित्र:Laxmi Prasad Devkota 1.jpg|alt=A photo of Devkota smoking (2013 BS (1956-1957))|thumb|चुरोट पिउँदै गरिरहेका कवि देवकोटा, विसं २०१३ साल]] लक्ष्मीप्रसाद देवकोटा जीवनकाल भरिनै निकै धुम्रपान गर्ने व्यक्ति थिए। देवकोटालाई वि.सं. २०१५ मा क्यान्सर लागेको थाहा भएको थियो। २०१६ सालमा उपचारका लागि सुरुमा भारत लगियो। त्यहाँ उनको आन्द्रा काटियो। पछि रुस लगियो। रुसका चिकित्सकहरूले सबैलाई गाली गरे। उनको आन्द्रा काट्नै नपर्ने भनेर। अब बिजोग भयो। भारतमा जचाँउदा आन्द्रै काटिदियो। रुसमा आन्द्रा काट्नै नपर्ने भन्यो। रोग लागेपछि उनको जीवन थप कष्टकर बन्यो।<ref name=":1" /> [[भारत]] लगेर ठूलो आन्द्राको ३ इन्च निकालिएपछि उनलाई आफू मृत्युको मुखमा आएको पक्का भएको थियो। त्यसपछि उनी रातभर जाग्राम बसी आफ्ना रचना लेख्न थालेका थिए। आफ्नो रोगको उपचारका लागि आवश्यक औषधि खरिद गर्न नसकेको दाबी गरेका थिए, यसबाहेक उनले खानासमेत किन्न निकै सङ्घर्ष गरिरहेका थिए। शान्त भवन अस्पतालमा रहँदा उनले आफ्ना साथी हरि श्रेष्ठलाई चिठीमा लेखेका थिए जुन यस प्रकार छ "मृत्यु मेरो अगाडि छ। म आकाशमा नक्षत्रहरू खोज्छु तर भेट्दिनँ। म आफूलाई शान्ति दिन सक्दिनँ । म उठ्न सक्ने भएँ, म आफू र आफ्ना बच्चाहरूलाई मार्ने थिएँ ।" जीवनभर, उनले भगवान् मानेनन् । आर्यघाटमा उनले भने 'मैले आफ्नो जिन्दगी हरिनाम नजपेर ,नास्तिक भएर बिताएछु, अब जान आँटिहालेँ" अनि उनले जीवनको शाश्वत आध्यात्मिक कुरा कवितामार्फत यसरी व्यक्त गरे। <ref>श्रेष्ठ, स्वयम्भूलाल, भानु, महाकवि देवकोटा विशेषाङ्क (२०२५ फागुन),'''महाकवि देवकोटा : संक्षिप्त जीवनी र केही क्षण''', भद्रपुर : भानु प्रकाशन</ref> :संसार रूपी सुख स्वर्गभित्र, :रमें, रमाएँ लिई भित्र चित्र । :सारा भयो त्यो मरूभूमि तुल्य, :रातै परेझैँ अब बुझ्छु बल्ल ॥१॥ :रहेछ संसार निशा समान, :आएन ज्यूँदै रहँदा नि ज्ञान । :आखिर श्रीकृष्ण रहेछ एक, :न भक्ति भो, ज्ञान, न भो विवेक ॥२॥ :महामरूमा कणझैँ म तातो, :जलेर मर्दो बिनु आश लाटो । :सुकी रहेको तरूझैँ छु खाली, :चिताग्नि तापी जल डाम्न फाली ॥३॥ :संस्कार आफ्नो सब नै गुमाएँ, :म शून्यमा शून्य सरी बिलाएँ । :जन्मे म यो स्वर्ग विषे पलाएँ, :आखिर मै खाक त्यसै बिलाएँ ॥४॥ शान्तभवनमा उनलाई हेर्न भीड लाग्ने गर्थ्यो। एकदिन [[राजा महेन्द्र]] उनको स्वास्थबारे जानकारी लिन आएका थिए। राजाले महाकविलाई सोधे , "तिमीलाई के चाहिन्छ?" त्यतिबेला देवकोटाले भने, "केही चाहिदैन सरकार, एउटा चुरोट भए पुग्छ।" त्यसपछि राजाले डुमरिया ब्रान्डको चुरोट खल्तीबाट निकालेर दिए।<ref>{{Cite news|title=एउटा चुरोट भए पुग्छ|last=केसी|first=विमलासिंह|date=२०६९ कार्तिक २५|work=नागरिक दैनिक}}</ref> उनलाई निको पार्न नसकिने पक्कापक्की भएपछि शान्तभवन अस्पतालबाट पशुपति आर्यघाटमा लाने मेलोमेसो गरिएको थियो । त्यस बेलासम्ममा देवकोटा चेतनशील थिए र उनलाई आफ्नो सम्भावित मृत्युको बारेमा पनि धेरै कुराको ज्ञान भइरहेको थियो। त्यति बेलासम्म पनि डा. एडगार आर. मिलरले महाकवि देवकोटालाई रगत दिएर थप केही दिन बचाउने इच्छा दर्शाएका थिए । तर उनको प्रस्तावमा देवकोटाले भनेका थिए, ‘‘डाक्टर ! किन यी युवकका रगत खेर फाल्ने ? तपाईंलाई थाहा छ, म मर्ने भैसकेको छु । टार्न नसकिने कुरालाई किन लम्ब्याउने ?’’<ref name=":2">{{Cite web |last=प्रसाई |first=नरेन्द्रराज |date=कात्तिक २९, २०७७ |title=महाकवि देवकोटाको जीवनको अन्तिम क्षण |url=https://baahrakhari.com/detail/296339 |access-date=2025-04-26 |website=बाह्रखरी }}{{Dead link|date=May 2026 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> देवकोटालाई रगत दिएर बचाउनेहरूप्रति उनले भदौ २६ गते कृतज्ञता ज्ञापन गरे । “दुई साहसी युवक भतिजा पद्मनाथ देवकोटा (लेखनाथ देवकोटाका कान्छा छोरा) र भोलामानसिंह थापा (पछि सहायक मन्त्री) ले मलाई रक्त प्रदान गरी २–४ दिनदेखि आजसम्म जियाए । उनीहरू चिरायु होऊन् । अब म मानवरक्त लिन्न र दिन चाहने व्यक्तिलाई धन्यवाद दिन्छु ।”<ref name=":2" /> देवकोटाको पीडा असह्य थियो र मर्नु पनि निश्चित भइसकेपछि उनी विष घुड्क्याएर भए पनि चाँडै क्यान्सरग्रस्त चोला बिसाउन पाए सन्चो हुन्थ्यो भन्ने चिन्तामा थिए । अस्पतालबाट पशुपति हिँडाइने बेलामा उनलाई हेर्न वासुदेव शर्मा लुइँटेल पनि शान्तभवन पुगेका थिए । लुइँटेल र देवकोटा खुबै मिल्थे । वास्तवमा लुइँटेलले देवकोटालाई सधैँ आदर, सम्मान र श्रद्धा नै गरिरहेका थिए । त्यसैले लुइँटेललाई भेट्नेबित्तिकै देवकोटाले आत्मीयता बाँड्दै भने “मलाई अलिकति विष ल्याइदिनुभएको छ ? मलाई डाहा भइरहेछ ! मलाई चाँडै मारिदिनुहोस् तपाईंलाई धर्म हुन्छ । पण्डितजी ! मलाई विष खान दिनुहोस् म मर्छु ।”<ref name=":2" /> देवकोटाले मृत्युशय्यामा बसेर नेपाली र अंग्रेजी भाषामा तीनवटा कविता लेखे । उनले त्यति बेला लेखेको अन्तिम नेपाली कविता एउटा ‘शून्यमा शून्यसरी’ अंग्रेजीमा लेखेको ‘लाइफ अफ द रिचेस्ट’ हरि श्रेष्ठलाई दिए । साथै उनले अंग्रेजी भाषामा लेखेको अन्तिम कविता ‘प्रमिथियन पेन आई बियर’ चाहिँ डा. एडगार आर. मिलरलाई दिएका थिए । देवकोटा अस्पतालको शय्यामा छटपट–छटपट नै गरिरहेका थिए । उनको वेदना, चित्कार र अवस्था देख्नेजति सबैका आँखा त्यस बेला रसाइरहेका हुन्थे । उनी क्रन्दनको ज्वाला फुटाएर भनिरहेका थिए “म किन बाँचिरहेको छु ?” आर्यघाट लाने बेलामा उनलाई सेतो भोटो र सुरुवाल फेराइएको थियो । अन्तिम यात्रा स्वरूप शान्तभवन अस्पतालमा उनलाई मोटरमा राखियो । उनी सुतेको मोटर २०१६ साल भदौ २७ गते बिहान ५.३० बजे पशुपति आर्यघाटतिर हुइँकियो । त्यति बेला आफन्तमाझ उनले भनिरहेका थिए, “अब म चौबीस घण्टाभन्दा बढी बाँच्न पाउँदिनँ ।” ===मृत्यु=== उनको मृत्युलाई यति तमासा बनाइयो। रोगले थलिएर हाडछाला मात्र भएका देवकोटाको फोटो खिच्ने र कविता बाचन गर्न लगाइने काम भयो। भदौ २९ गते प्रधानमन्त्री [[विश्वेश्वरप्रसाद कोइराला|बीपी कोइराला]]का तर्फबाट निर्माण तथा सञ्चार मन्त्री [[गणेशमान सिंह]]ले पशुपति आर्यघाट पुगी महाकवि देवकोटासँग उनको अन्तिम इच्छाबारे सोधेका थिए । मन्त्री सिंहसंग देवकोटाले आफ्नो ऋण र छोराहरुको पढाइबारे चिन्ता व्यक्त गरे । त्यो बेला महाकविको २२ हजार ऋण रहेछ । सरकारले पूरै ऋण तिर्ने बचन दिएकै दिन उनको निधन भयो । <ref name=":0" /> क्यान्सर रोगसँगको लामो सङ्घर्षपछि देवकोटाको विसं २०१६ साल भाद्र २९ साँझ ([[मदनमणि दीक्षित|मदनमणि दिक्षित]]को अनुसार ६ बजे) [[काठमाडौँ]]को [[पशुपतिनाथ मन्दिर]]स्थित बागमती नदीको किनारमा रहेको [[आर्यघाट]]मा निधन भएको थियो। === प्रतिकृया === भदौ २९ गते सरकारले महाकविको शोकमा दिउँसो २ बजेपछि सिंहदरबार सचिवालय र अरु अड्डामा बिदा दियो भने सबै शिक्षण संस्था एक दिन बन्द गरिए । देवकोटाको निधनप्रति दुःख व्यक्त गर्दै प्रधानमन्त्री [[विश्वेश्वरप्रसाद कोइराला|बीपी कोइराला]]ले २०१६ भदौ ३० गते [[प्रतिनिधि सभा (नेपाल)|प्रतिनिधि सभा]] बैठकमा भनेका थिए— “नेपाली साहित्य जगतका एक महान् विभूति महाकवि देवकोटाको असामयिक निधनबाट देशलाई ठूलो क्षति भएको छ। नेपालको सबभन्दा ठूलो साहित्यिक, मलाई त यो भन्नमा अत्युक्ति लाग्दैन कि नेपाली साहित्यको इतिहासको सबभन्दा ठूलो व्यक्तिको निधन भयो।” प्रधानमन्त्रीले प्रतिनिधि सभा र महासभामा बैठक स्थगन प्रस्ताव राखेपछि दुवै सदनमा २ मिनेट मौन धारण गरेर महाकविप्रति श्रद्धाञ्जली अर्पण गरियो ।<ref name=":0">{{Cite news|url=https://anweshannews.com/news/details/259|title=सरकारले तिरेको थियो, महाकविको २२ हजार ऋण|last=अन्वेषण सम्वाददाता|work=अन्वेषण}}{{Dead link|date=July 2025 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> महाकविप्रति श्रद्धाञ्जली अर्पण गर्दै [[नेपाल राष्ट्रवादी गोर्खा परिषद्|राष्ट्रिय गोरखा परिषद्]] नेता मृगेन्द्रशमशेर राणाले भने, “देवकोटा नेपालको साहित्यिकजगत्को मात्र होइन कि नेपालभरको एउटा तारा हुनुहुन्थ्यो । उहाँको निधन भो भन्ने त मलाई लाग्दैन । त्यसैले आज हामी उहाँलाई श्रद्धाञ्जली अर्पण गर्न आएका छौं भन्ने मलाई लाग्छ । त्यो विभूति हाम्रा अगाडि छैन । हामीमा ठूलो क्षति भएको छ । उहाँको मृत्यु भो भन्ने मलाई लाग्दैन उहाँ मर्नु भएको छैन । मर्नुहुने पनि छैन । जो मानिस १ करोड जनताको हृदयमा बसेको छ, त्यो मानिस मर्न सक्तैन, मर्ने छैन ।”<ref name=":0" /> [[नेपाल कम्युनिस्ट पार्टी]]का [[तुलसीलाल अमात्य]]ले भने, “देवकोटाजीको निधनले हाम्रो देशको साहित्यलाई मात्र होइन, संसारको साहित्यलाई नै एउटा ठूलो धक्का दिएको छ ।” <ref name=":0" /> == देवकोटाका केही प्रमुख कृतिहरू == '''१. कविता सङ्ग्रह:''' [[पहाडी पुकार]] ( वि. सं. २००५)•[[पुतली (बाल कविता)]]• वि. सं. २००९)• [[भिखारी]] ( वि. सं. २०१०) •[[सुनको बिहान]] ( वि.सं.२०१०) •[[छहरा]] (वि. सं. २०१२)• जन्मोत्सव र मुटुको थोपा ( वि.सं.२०१५) • [[मृत्युशैयाबाट]] ( वि. सं.२०१६) •[[चिल्ला पातहरू]] (मृत्युपश्चात प्रकाशित, वि.सं. २०२१) •गाइने गीतहरू (मृत्युपश्चात प्रकासित, वि.सं. २०२४) •मनोरञ्जन (मृत्युपश्चात प्रकाशित, वि. सं. २०२४) • [[भावना गाङ्गेय]] (मृत्युपश्चात प्रकाशित, वि. सं. २०२४)• [[आकाश बोल्छ]] (मृत्युपश्चात् प्रकाशित, वि. सं. २०२५) • [[छाँगासँग कुरा]] (मृत्युपश्चात् प्रकाशित, वि. सं. २०२६), •[[लक्ष्मी कविता सङ्ग्रह]] ( मृत्युपश्चात प्रकाशित, वि. सं. २०३३) • [[लक्ष्मी गीत सङ्ग्रह]] (मृत्युपश्चात प्रकाशित, वि. सं. २०४०) '''२.खण्डकाव्य :''' [[मुनामदन]] ( प्रकाशन वर्ष, वि. सं. १९९१) , [[राजकुमार प्रभाकर]] (वि. सं. १९९७), [[कुञ्जिनी]] (वि. सं. २००२), [[वसन्ती गीतीकाव्य]](वि. सं. २००९), [[मैनाचरी|मैना]] (वि. सं. २००९), [[सुन्दरी जर्पिना]] (वि. सं. २००९), [[रावण जटायु युद्ध]] (वि. सं. २०११) , [[म्हेन्दु]] (वि. सं. २०१५), [[लुनी]] (वि. सं. २०२३), [[सीताहरण]] (वि. सं. २०२४), [[मायाविनि सर्सी]] (वि. सं. २०२४), [[नवरस कोश काव्य]] (वि. सं. २०२५), [[मैनाचरी|मैना]] ( पुन: सम्पादन वि. सं. २०३९)। ३.'''निबन्ध''': [[आषाढको पन्ध्र]](वि. सं. १९९३,शारदा), [[भलादमी]], [[फूल]], [[पहाडी जीवन]], [[हाई हाई अङ्ग्रेजी]], [[के नेपाल सानो छ]], [[कला र जीवन]], [[कल्पना]], [[साधुको महात्म्य]], [[निद्रा श्रीपञ्चमीको दिन वि. सं. २०१०]], [[साँढे]],[[मेरो पाल्पा तानसेन तर्फको यात्रा]] आदि । {{Table |type=class="wikitable sortable" |title= लक्ष्मीप्रसाद देवकोटाका कविता सङ्ग्रहहरू |hdrs= प्रकाशन मिति!!शीर्षक!!विधा |row1= वि. सं. २००५ {{!!}} [[पहाडी पुकार]] {{!!}} कविता |row2= वि. सं.२००९ {{!!}} [[पुतली(बाल कविता)|पुतली]] {{!!}} कविता |row3= वि. सं.२०१० {{!!}} [[भिखारी]] {{!!}} कविता |row4= वि. सं. २०१० {{!!}} [[सुनको बिहान]] {{!!}} कविता |row5= वि. सं. २०१२ {{!!}} [[छहरा]] {{!!}} कविता |row6= वि. सं. २०१५ {{!!}} जन्मोत्सव र मुटुको थोपा {{!!}} ?? |row7= वि. सं. २०१६ {{!!}} [[मृत्युशैयाबाट]] {{!!}} कविता |row8= वि. सं. २०२१ {{!!}} [[चिल्ला पातहरू]] {{!!}} ?? |row9= वि. सं. २०२४ {{!!}} गाईने गीतहरू {{!!}} गीत |row10= वि. सं. २०२४ {{!!}} मनोरञ्जन {{!!}} कविता |row11= वि. सं. २०२४ {{!!}} [[भावना गाङ्गेय]] {{!!}} ?? |row12= वि. सं. २०२४ {{!!}} [[आकाश बोल्छ]] {{!!}} ?? |row13= वि. सं. २०२६ {{!!}} [[छाँगासँग कुरा]] {{!!}} ?? |row14= वि. सं. २०३३ {{!!}} [[लक्ष्मी कविता सङ्ग्रह]] {{!!}} कविता |row15= वि. सं. २०४० {{!!}} [[लक्ष्मी गीत सङ्ग्रह]] {{!!}} गीत }} देवकोटाको कवितायात्राको पूर्वार्द्धकालीन कविता सङ्ग्रहहरूमा ''भिखारी'' कविता सङ्ग्रहलाई, खण्डकाव्यहरूमा ''[[मुनामदन]]'' खण्डकाव्यलाई र महाकाव्यहरूमा '[[शाकुन्तल (महाकाव्य)|शाकुन्तल]]' महाकाव्यलाई प्रतिनिधिकृतिका रूपमा लिन सकिन्छ। उनको उत्तरार्द्धकालीन कवितायात्राका कविता सङ्ग्रहहरूमा ''लक्ष्मी कविता सङ्ग्रह''लाई, खण्डकाव्यहरूमा ''मायाविनी सर्सी'' खण्डकाव्यलाई र महाकाव्यमा ''प्रमिथस'' महाकाव्यलाई प्रतिनिधिकृति मान्न सकिन्छ। यसैगरी देवकोटाका बालकविताहरूका प्रतिनिधिकृतिका रूपमा उनका ''सुनको बिहान'' र ''पुतली'' बालकविता सङ्ग्रहलाई अघि सार्न सकिन्छ भने उनका हाँस्यव्यङ्ग्य कविताहरूको प्रतिनिधित्व उनको 'मनोरञ्जन हाँस्यव्यङ्ग्य कविता सङ्ग्रहले र गीतिकविता वा गीतहरूको प्रतिनिधित्वचाहिँ उनको ''लक्ष्मी गीति सङ्ग्रह''ले गर्दछ। यस सन्दर्भमा देवकोटाका विशुद्ध प्रगतिवादी क्रान्तिकारी कविताहरूको प्रतिनिधित्व गर्ने ''पहाडी पुकार''लाई र उनको रोमान्टिक प्रगतिवादी क्रान्तिकारी गीति नाट्य ''कृषिबाला''लाई पनि उल्लेखनीय छन्। ==देवकोटा:विश्लेषण == [[श्यामदास वैष्णव]] देवकोटाको परिचय यसरी गर्छन् : लक्ष्मीप्रसाद देवकोटा अत्यन्तै प्रतिभाशाली व्यक्ति हुनुहुन्थ्यो। नेपाली साहित्यमा धेरै कुरा रच्नुभयो उहाँले। बाल साहित्यदेखि महाकाव्यसम्म रचना गर्नुभयो। उहाँका कृति विश्वविद्यालयमा राखियो। देशको महाकवि भएर उहाँले धेरै ठाउँमा योगदान दिनु भएको छ, देवकोटाले भाषा अनुवाद संस्थानमा पनि काम गर्नु भएको थियो। त्रिचन्द्र कलेजमा पढाउनु भयो। एकेडेमी बनाउन मद्दत गर्नुभयो। धेरै समयपछि मन्न्री पनि हुनुभयो। कवि सम्मेलनमा नेपालको तर्फबाट देश विदेश जानुहुन्थ्यो। उहाँको मृत्यु भने दुखद् तवरले भयो ।<ref name=setopati>शोभा शर्मा, '''[http://setopati.com/sahityapati/19107 देवकोटाले कोट फुकालेर दिन्थे, पैसा बाँड्थे भन्ने साँचो होइन] {{Webarchive|url=https://web.archive.org/web/20141028180824/http://setopati.com/sahityapati/19107/ |date=2014-10-28 }}''' Setopati.com,प्रकाशित मिति: बिहीबार, कार्तिक ६, २०७१ १४:२२:३३</ref> वैष्णवले थपे -"महाकविले भाषा अनुवादमा काम गरेर पुस्तक लेखेर अनि ट्युसन पढाएर पैसा कमाउनु हुन्थ्योे। तैपनि दुःख भने थियो ।" वैष्णवले भने, 'तर बाटोमा गरीब देखे आफ्नो कोट नै फुकालेर दिन्थे पैसा बाड्दै हिँड्थे भन्छन् नि त्यस्तो भने होइन।"<ref name=setopati /> == तस्वीरहरू == <gallery> File:Laxmi prasad devkota stamp 2.JPG|देवकोटाको तस्वीर भएको हुलाक टिकट File:Statue of Laxmi Prasad Devkota-TU-9653.jpg|[[त्रिभुवन विश्वविद्यालय]]मा रहेको अर्धकदको सालिक File:Mahakavi laxmi prasad devkota.jpg|देवकोटाको तस्वीर File:महाकवी, राष्ट्रकवी, र हरिवंश राय बच्चन.webp|thumb|महाकवी, राष्ट्रकवी, र हरिवंश राय बच्चन File:लक्ष्मीप्रसाद देवकोटा.jpg|thumb|लक्ष्मीप्रसाद देवकोटा </gallery> ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} ==यो पनि हेर्नुहोस्== *[[पागल (कविता)]] *[[लक्ष्मीप्रसाद देवकोटा रचनासूची]] ==बाह्य कडीहरू== {{wikiquote|लक्ष्मीप्रसाद देवकोटा}} {{commonscat|Laxmi Prasad Devkota}} # [https://www.nepalilekh.com/Author/Laxmi-Prasad-Devkota/ लक्ष्मीप्रसाद देवकोटाका रचनाहरू (नेपाली लेख डट कम)] {{Webarchive|url=https://web.archive.org/web/20250117043028/https://www.nepalilekh.com/Author/Laxmi-Prasad-Devkota/ |date=2025-01-17 }} # [http://www.youtube.com/v/p0jZ9CanqL0 लक्ष्मीप्रसाद देवकोटाको स्वरमा केही कविताहरू, बीबीसीको कार्यक्रमबाट] # [http://www.spinybabbler.org/literature/personalities/laxmi_prasad_devkota.htm देवकोटाको जीवनी] {{Webarchive|url=https://web.archive.org/web/20051016103642/http://www.spinybabbler.org/literature/personalities/laxmi_prasad_devkota.htm |date=2005-10-16 }} # [http://english.ohmynews.com/articleview/article_view.asp?no=259733&rel_no=1 लक्ष्मीप्रसाद देवकोटा: नेपालका सर्वोत्कृष्ट कवि] {{Webarchive|url=https://web.archive.org/web/20120314032950/http://english.ohmynews.com/articleview/article_view.asp?no=259733&rel_no=1 |date=2012-03-14 }} # [http://literature.wnso.org/2002/munamadan.htm मुना-मदन] # [http://www.newssewa.com/content/devkota.htm देवकोटा भन्थे : कवी काम लाग्ने पागल अरु बेकामका पागल (देवकोटाको अडियो सहित)]{{Dead link|date=September 2023 |bot=InternetArchiveBot |fix-attempted=yes }} #[http://annapurnapost.com/News.aspx/story/46493 लक्ष्मीप्रसाद देवकोटाले मृत्यु भन्दा पहिले आफ्ना आफन्तहरूसँग गरेको कुराकानी] {{Webarchive|url=https://web.archive.org/web/20160403080927/http://www.annapurnapost.com/News.aspx/story/46493 |date=2016-04-03 }} {{लक्ष्मीप्रसाद देवकोटाका कृतिहरू}} {{नेपाली भाषाका साहित्यकारहरू}} [[श्रेणी:नेपाली साहित्यकारहरू]] [[श्रेणी:साझा पुरस्कार विजेताहरू]] [[श्रेणी:सन् १९०९ मा जन्म]] [[श्रेणी:लक्ष्मीप्रसाद देवकोटा| ]] [[श्रेणी:खस जाति]] [[श्रेणी:नेपाली शिक्षकहरू]] 2ppwkj3jz7kmzmda3l6ohl3klh9qcer त्रिभुवन विश्वविद्यालय 0 6813 1361479 1348523 2026-06-12T10:44:07Z Bishaldev100 28807 /* यी पनि हेर्नुहोस */ 1361479 wikitext text/x-wiki {{Infobox university | name = त्रिभुवन विश्वविद्यालय | image_name =File:Tribhuvan University of Nepal-IMG 9517.JPG | image_size = 160px | caption = [[त्रिभुवन विश्वविद्यालय]] | motto = *नेपालको समग्र विकासको निम्ति दक्ष मानवशक्ति उत्पादन गर्नु<br> *देशको सांस्कृतिक विरासतको रक्षा गर्नु <br> *सञ्चित, उन्नत र ज्ञान प्रसार <br> *कलाको निम्ति प्रोत्साहित गर्नु, *विज्ञानको क्षेत्रमा अनुसंधानलाई बढावा दिनु, *व्यावसायिक क्षेत्र एवं प्रौद्योगिकीको निम्ति प्रोत्साहित गर्नु | established = २०१६ साल | type = पब्लिक विद्यालय | endowment = | chancellor = [[नेपालका प्रधानमन्त्रीहरूको सूची|नेपालको प्रधानमन्त्री]] [[बालेन शाह]] | vice_chancellor = प्रा डा दिपक अर्याल | chairman = | faculty = ७,०४९ प्राध्यापकीय संकाय<br />५६०७ अन्य संकाय <ref name="Tribhuvan University">[http://www.tribhuvan-university.edu.np/home/tribhuvan.htm Tribhuvan University] {{Webarchive|url=https://archive.is/20071006012638/http://www.tribhuvan-university.edu.np/home/tribhuvan.htm |date=2007-10-06 }}</ref> | students = ६,०४,४३७ <ref>{{cite web|url=http://tribhuvan-university.edu.np/about-us/|title=Tribhuvan university}} {{Webarchive|url=https://web.archive.org/web/20180903001952/http://tribhuvan-university.edu.np/about-us |date=2018-09-03 }}</ref> | city = [[कीर्तिपुर नगरपालिका|कीर्तिपुर]], [[काठमाडौँ (स्पष्टता)|काठमाडौँ]], | country = [[नेपाल]] | campus = [[कीर्तिपुर नगरपालिका|कीर्तिपुर]] | website = {{URL|http://www.tribhuvan-university.edu.np|त्रिभुवन-युनिभर्सिटी.इडीयु.एनपी}} }} '''त्रिभुवन विश्वविद्यालय''' वा '''त्रिवि''' (अङ्ग्रेजी : '''Tribhuvan University''' वा '''TU''') [[नेपाल]]को सबैभन्दा पुरानो र ठूलो विश्वविद्यालय हुनुका साथै उच्च शिक्षाका लागि नेपालको पहिलो राष्ट्रिय शैक्षिक संस्था पनि हो । यस विश्वविद्यालयको केन्द्रीय कार्यालय [[कीर्तिपुर नगरपालिका|कीर्तिपुर]] [[काठमाडौँ]]मा छ । यस विश्वविद्यालय ३०४२–५–२ रोपनी क्षेत्रफलमा फैलिएको छ । त्रिभुवन विश्वविद्यालय अन्तर्गत पाँचवटा प्राविधिक शैक्षिक संस्था र चारवटा साधारण संकाय सञ्चालित छन् । यसले पचासवटा प्राविधिक शीर्षकमा प्रमाण–पत्र तहको शिक्षा दिइरहेको छ त्यस्तै १०७९ शीर्षकमा स्नातक तथा १ हजार शीर्षकमा स्नातकोत्तर शीर्षकमा शिक्षा प्रदान गरिरहेको छ । यसका साथै यसले पीएचडी का लागि समेत विभिन्न शीर्षकमा प्राविधिक तथा संकायस्तरीय शिक्षा दिइरहेको छ । त्रिभुवन विश्वविद्यालय अन्तर्गत ९३१ वटा निजी क्याम्पसले सम्बन्धन लिएका छन् । सन् २०१३–१४ सम्म यसमा ६,०४,४३७ जना विद्यार्थीहररु विभिन्न शैक्षिक तहमा सामेल भएका छन् । त्रिभुवन विश्वविद्यालयमा ७९६६ अध्यापन संकाय छन् । त्रिभुवन विश्वविद्यालयमा १५,१९६ कर्मचारी कार्यरत छन् । [[कृषि तथा पशु विज्ञान अध्ययन संस्थान|कृषि तथा पशु विज्ञान]], वन विज्ञान, [[इन्जिनियरिङ अध्ययन संस्थान|इञ्जिनीयरिङ]], विज्ञान तथा प्रविधि, [[चिकित्साशास्त्र अध्ययन संस्थान|चिकित्साशास्त्र]], समाजविज्ञान, भूगर्भशास्त्र [[मानवशास्त्र]], [[व्यवस्थापन]], [[शिक्षाशास्त्र]], कानुन तथा मानविकिमा यो विश्वविद्यालयले शिक्षा प्रदान गरिरहेको छ । ३८ केन्द्रीय विभागहरू समेत गरी यस विश्वविद्यालयका ६० आंगिक क्याम्पस रहेका छन् । [[File:TU building.jpg|thumb|200px|right|त्रिभुवन विश्वविद्यालय]] ==इतिहास== त्रिभुवन विश्वविद्यालयको स्थापना राजा [[त्रिभुवन वीरविक्रम शाह|त्रिभुवन]]को नाममा नामकरण गरिएको छ । यस विश्वविद्यालयको स्थापना वि.स.२०१६ सालमा भएको हो । यो नेपालको सबैभन्दा पुरानो विश्वविद्यालय हो । <ref>{{cite web|url=http://tribhuvan-university.edu.np/about-us/|title=Tribhuvan university - About us}} {{Webarchive|url=https://web.archive.org/web/20180903001952/http://tribhuvan-university.edu.np/about-us |date=2018-09-03 }}</ref> == अध्ययन संस्थान == === इन्जिनियरिङ अध्ययन संस्थान=== {{मुख्य|इन्जिनियरिङ अध्ययन संस्थान}} === कृषि तथा पशु विज्ञान अध्ययन संस्थान === {{मुख्य|कृषि तथा पशु विज्ञान अध्ययन संस्थान}} === चिकित्सा शास्त्र अध्ययन संस्थान === === विज्ञान तथा प्रविधि अध्ययन संस्थान === === वन विज्ञान अध्ययन संस्थान === == संकाय == [[कानुन संकाय]] [[मानविकी तथा सामाजिकशास्त्र संकाय]] [[व्यवस्थापन संकाय]] [[शिक्षाशास्त्र संकाय]] ==संक्षिप्तमा त्रि. वि. ऐन, नियम== ===त्रिभुवन विश्वविद्यालय ऐन, २०४९=== वि. सं. २०१६ सालमा स्थापना भएको त्रिभुवन विश्वविद्यालयलाई नेपालको सर्वाङ्गीण विकासको लागि आवश्यक दक्ष जनशक्ति तयार गर्न, स्तरयुक्त उच्च शिक्षा प्रदान गर्न, विविध पक्षमा अनुसन्धान गर्न, राष्ट्रिय संस्कृति र परम्पराको संरक्षण र विकास गर्न, कला, विज्ञान, प्रविधि तथा व्यावसायिक क्षेत्रको ज्ञान र अनुसन्धानलाई व्यापक एवं व्यवहारिक र समय सापेक्ष बनाउने क्रममा त्रिभुवन विश्वविद्यालयलाई बढी सक्षम बनाउन वाञ्छनीय भएकोले संसदले त्रिभुवन विश्वविद्यालय ऐन, २०४९ बनाएको हो।<ref> प्रस्तावना, त्रि. वि. ऐन २०४९ </ref> *त्रिभुवन विश्वविद्यालय अविच्छिन्न उत्तराधिकारवाला एक स्वशासित र सङ्गठित संस्था हो। यसले व्यक्ति सरह चल अचल सम्पत्ति प्राप्त गर्न, उपभोग गर्न, बेचबिखन गर्न वा अन्य किसिमले व्यवस्था गर्न सक्दछ। विश्वविद्यालयले व्यक्ति सरह आफ्नो नामबाट नालिस उजुर गर्न र विश्वविद्यालय उपर पनि सोही नामबाट नालिस उजुरसमेत गर्न सक्दछ। <ref> त्रि. वि. ऐन २०४९ को दफा ४ </ref> *विश्वविद्यालयको संंगठन विश्वविद्यालयको सङ्गठन देहाय बमोजिम हुनेछ । यिनीहरूको सामुहिक रूप नै विश्वविद्यालयको स्वरूप हुनेछ । (क) विश्वविद्यालय सभा, (ख) प्राज्ञिक परिषद्, (ग) कार्यकारी परिषद्, (घ) सेवा आयोग, (ङ) अध्ययन संस्थान, (च) सङ्काय, (छ) विभाग, (ज) आङ्गिक क्याम्पस,(आङ्गिक महाविद्यालय) (झ) सम्बन्धन प्राप्त क्याम्पस, (सम्बन्धन प्राप्त महाविद्यालय) (ञ) अनुसन्धान केन्द्र र (ट) अन्य निकायहरू । <ref> त्रि. वि. ऐन २०४९ को दफा ६ </ref> * कार्यकारी परिषद्को गठन विश्वविद्यालयको कार्यकारी निकायको रूपमा काम गर्न देहायका सदस्यहरू रहेको कार्यकारी परिषद्् गठन गरिएको हुन्छ। (क) उप-कुलपति (अध्यक्ष) (ख) शिक्षाध्यक्ष (सदस्य) (ग) अध्ययन संस्थानका डीनहरू मध्येबाट एकजना (सदस्य) (घ) संकायका डीनहरू मध्येबाट एकजना (सदस्य) (ङ) रजिष्ट्रार (सदस्य-सचिव) <ref> त्रि. वि. ऐन २०४९ को दफा १३ को उपदफा १ </ref> ===त्रिभुवन विश्वविद्यालय नियम=== ==== शिक्षक कर्मचारी सेवा संबन्धी नियम, २०५० ==== *[[विश्वविद्यालयमा]] रहने पद तथा श्रेणीहरू:- (क) शिक्षकतर्फ: १. प्राध्यापक २. सहप्राध्यापक ३. उपप्राध्यापक ४. सहायकप्राध्यापक ५. शिक्षण सहायक [शिक्षण सहायक पद अस्थायी हुन्छ। यस पदमा करार सेवामा मात्र पदपुर्ति गरिन्छ। शिक्षण सहायक संबन्धि अन्य व्यवस्था तोकिए अनुसार हुन्छ।] (ख) अधिकृत स्तरका कर्मचारीतर्फ: १. प्रशासक वा सो सरह (विशिष्ट श्रेणी) २. सहप्रशासक वा सो सरह (प्रथमश्रेणी) ३. उपप्रशासक वा सो सरह (द्वितीयश्रेणी) ४. सहायकप्रशासक वा सो सरह (तृतीय श्रेणी) <ref> त्रि. वि. शिक्षक कर्मचारी सेवा संबन्धी नियम, २०५० को नियम ५ को उपनियम १ </ref> यस बाहेक कार्यकारी परिषदले आवश्यकता अनुसार ती पद र श्रेणी भन्दा मुनिको श्रेणीसहित वा विहीनका पदहरू तोक्न सक्दछ। <ref> त्रि. वि. शिक्षक कर्मचारी सेवा संबन्धी नियम, २०५० को नियम ५ को उपनियम २ </ref> ==== सङ्गठन तथा शैक्षिक प्रशासन संबन्धी नियम, २०५० ==== *विद्या परिषद्को गठन: अध्ययन संस्थान र संकायको प्राज्ञिक निकायको रूपमा काम गर्न प्रत्येक अध्ययन संस्थान र प्रत्येक संकायमा बेग्लाबेग्लै एक विद्या परिषद् रहनेछ, जसको गठन देहाय अनुसार हुन्छ। (क) डीन (अध्यक्ष) (ख) विभिन्न विषय समितिका अध्यक्ष (सदस्य) (ग) संबन्धित अध्ययन संस्थान वा संकायमा कार्यरत प्राध्यापकहरु वा कम्तिमा १० वर्ष स्थायी सेवा पुर्याइसकेका शिक्षकहरू मध्येबाट ५ जना (सदस्य) (घ) अनुसन्धान केन्द्रका संबन्धित विषयका कार्यकारी निर्देशकहरू मध्येबाट १ जना (सदस्य) (ङ) परीक्षा नियन्त्रक (सदस्य) (च) पाठ्यक्रम विकास केन्द्रका कार्यकारी निर्देशक (सदस्य) (छ) आङ्गिक र सम्बन्धन प्राप्त क्याम्पसको प्रमुखहरू मध्येबाट ५ जना (सदस्य) (ज) तयार भएको जनशक्ति प्रयोग गर्ने निकाय समेत प्रतिनिधित्व हुने गरी बढीमा ५ जना (सदस्य) <ref> त्रि. वि. सङ्गठन तथा शैक्षिक प्रशासन संबन्धी नियम, २०५० को नियम १३५ को उपनियम १ </ref> ==== विकेन्द्रीकरण नियम, २०५५ ==== * व्यवस्थापन तथा विकास परिषद् आर्थिक स्थिति, प्राज्ञिक दक्षता तथा संस्थागत क्षमताको आधारमा कार्यकारी परिषद्ले तोकेको अध्ययन संस्थान वा संकाय वा अनुसन्धान केन्द्रको लागि व्यवस्थापन तथा विकास परिषद् गठन गरिन्छ। त्यस्तो परिषद् सम्बन्धित अध्ययन संस्थान वा संकाय वा अनुसन्धान केन्द्रको नाम अन्तर्गत प्रचलित हुनेछ। <ref> त्रि. वि. विकेन्द्रीकरण नियम, २०५५ को नियम ३ को उपनियम १ </ref> == उप कुलपति == उप–कुलपति [[विश्वविद्यालय]]मा पूरा समय काम गर्ने [[प्रमुख पदाधिकारी]] । हालसम्म निम्न उप–कुलपति रहेका थिए । {| class="wikitable" |+ !क्र स !नाम !देखी !सम्म |- |१ |[[सुवर्ण शमशेर राणा|सुवर्णशम्शेर राणा]] | | |- |२ |शारदाप्रसाद उपाध्याय | | |- |३ |[[रुद्रराज पाण्डे]] | | |- |४ |त्रैलोक्यनाथ उप्रेती | | |- |५ |सूर्यबहादुर शाक्य | | |- |६ |जगतमोहन अधिकारी | | |- |७ |डा. महेन्द्र प्रसाद | | |- |८ |वी.सी. मल्ल | | |- |९ |केदारभक्त माथेमा | | |- |१० |कमलकृष्ण जोशी | | |- |११ |नवीनप्रकाश जंग शाह | | |- |१२ |गोविन्दप्रसाद शर्मा | | |- |१३ |माधवप्रसाद शर्मा | | |- |१४ |Bhim Bahadur Karki | | |- |१५ |Surya Bahadur Thapa | | |- |१६ |Jagannath Prasad Sharma | | |- |१७ |Hari Prasad Sharma | | |- |१८ |Chandra Mani Adhikari | | |- |१९ |Prem Nath Pande | | |- |२० |Ram Prasad Upadhyay | | |- | |Kedar Bhakta Mathema | | |- | |Dilli Ram Regmi | | |- | |Hira Bahadur Maharjan | | |- | |Tirth Raj Khaniya | | |- | |Dharma Kanta Baskota | | |- | |Keshar Jung Baral | | |- | | | | |} ==शैक्षिक== ==सन्दर्भ सामग्री== {{reflist}} ==यी पनि हेर्नुहोस== * [[त्रिभुवन विश्वविद्यालय केन्द्रीय पुस्तकालय]] * [[त्रिभुवन विश्वविद्यालय अन्तर्राष्ट्रिय क्रिकेट मैदान]] * [[त्रिभुवन विश्वविद्यालय शिक्षण अस्पताल]] {{नेपालका विश्वविद्यालयहरू}} ==बाह्य लिंक== # [http://www.tribhuvan-university.edu.np त्रिभुवन विश्वविद्यालयको वेवसाइट] [[श्रेणी:नेपालका विश्वविद्यालयहरू]] [[श्रेणी:नेपालका प्रमुख क्याम्पसहरू]] [[श्रेणी:त्रिभुवन विश्वविद्यालय| ]] csxud3lihsbcbplebag4jx53x459jzf राष्ट्रिय अनुसन्धान विभाग 0 7113 1361180 1330391 2026-06-12T01:55:30Z Aayush Dhital 79298 /* */ 1361180 wikitext text/x-wiki {{Infobox Government agency | agency_name = National Investigation Department | nativename = '''राष्ट्रिय अनुसन्धान विभाग''' | nativename_a = | nativename_r = | logo = | logo_width = | logo_caption = | seal = Emblem_of_Nepal_(alternative).svg | seal_width = 125 px | seal_caption = | formed = वि.सं २००८ | preceding1 = | preceding2 = | dissolved = | superseding = | jurisdiction = नेपाल | headquarters = सिंहदरवार, काठमाण्डौ | employees = | budget = | minister1_name = | minister1_pfo = | minister2_name = | minister2_pfo = | chief1_name = '''टिकेन्द्र कार्की''' | chief1_position = <br /> अतिरिक्त मुख्य अनुसन्धान निर्देशक | chief2_name = | chief2_position = | parent_agency = प्रधानमन्त्री तथा मन्त्रिपरिषद्को कार्यालय | website = {{URL|nidept.gov.np}} | footnotes = }} '''राष्ट्रिय अनुसन्धान विभाग''' नेपालको संविधानमा व्यवस्था भए वमोजिम संघमा रहने गरी स्थापित इन्टेलिजेन्स संस्था हो । राष्ट्रिय हित एवं सुरक्षाका बारे आवश्यक खबर संकलन गर्ने र संकलित खबरहरुको अध्ययन, मुल्याङ्कन, बिश्लेषण र सम्पादन गरी सरकारलाई पूर्व जानकारी दिने उद्देश्यले स्थापित रहेको छ । <br /> नेपाल राज्यको स्वतन्त्रता, सार्वभौमसत्ता, भौगोलिक अखण्डता, स्वाधिनताको रक्षा, आन्तरिक एवं राष्ट्रिय सुरक्षा र हितको प्रवर्द्धन एवं सम्वर्द्धन गर्नका निम्ति सरकारलाई आवश्यक पर्ने सबै प्रकारका सूचना उपलव्ध गराउने यो संगठनको जिम्मेवारी हो । राष्ट्रिय सुरक्षाका विभिन्न क्षेत्रका अतिरिक्त आर्थिक एवं वित्तीय अपराध, आतंकवाद, संगठित अपराधलगायतका अपराध, धर्म, सस्कृति, भाषा, समुदायवीचको सद्भावमा खलल पुर्‍याउने पक्षसंग सम्वन्धित सूचना संकलन पनि विभागको महत्वपूर्ण कार्यभार हो । == '''हालसम्मका प्रमुखहरू'''== #रोमबहादुर थापा #पदमबहादुर शाह #धुन्डीराज शर्मा #हर्क बहादुर थापा #रामप्रसाद श्रेष्ठ #चन्दबहादुर राई #लेखबहादुर पाण्डे #विष्णुराज पन्त #गोविन्दकर्म थापा #हरिबाबु चौधरी #देवीराम शर्मा #धनसिंह कार्की #अशोकदेव भट्ट #मोतीबहादुर गुरुङ #जितबहादुर केसी #दिलीपराज रेग्मी #गणेशप्रसाद अधिकारी #यदुलाल खरेल #'''हुतराज थापा''' ==यो पनि हेर्नुहोस्== * [[नेपाली सेना]] * [[नेपाल प्रहरी]] * [[नेपाल सशस्त्र प्रहरी बल|नेपाल ससस्त्र प्रहरी बल]] {{stub}} aycaov9pdlodkwmb9nvcg1lfdcj4o6u 1361183 1361180 2026-06-12T01:56:52Z Aayush Dhital 79298 /* */ 1361183 wikitext text/x-wiki {{Infobox Government agency | agency_name = National Investigation Department | nativename = '''राष्ट्रिय अनुसन्धान विभाग''' | nativename_a = | nativename_r = | logo = | logo_width = | logo_caption = | seal = Emblem_of_Nepal_(alternative).svg | seal_width = 125 px | seal_caption = | formed = वि.सं २००८ | preceding1 = | preceding2 = | dissolved = | superseding = | jurisdiction = नेपाल | headquarters = सिंहदरवार, काठमाण्डौ | employees = | budget = | minister1_name = | minister1_pfo = | minister2_name = | minister2_pfo = | chief1_name = '''टिकेन्द्र कार्की''' | chief1_position = <br /> मुख्य अनुसन्धान निर्देशक | chief2_name = | chief2_position = | parent_agency = प्रधानमन्त्री तथा मन्त्रिपरिषद्को कार्यालय | website = {{URL|nidept.gov.np}} | footnotes = }} '''राष्ट्रिय अनुसन्धान विभाग''' नेपालको संविधानमा व्यवस्था भए वमोजिम संघमा रहने गरी स्थापित इन्टेलिजेन्स संस्था हो । राष्ट्रिय हित एवं सुरक्षाका बारे आवश्यक खबर संकलन गर्ने र संकलित खबरहरुको अध्ययन, मुल्याङ्कन, बिश्लेषण र सम्पादन गरी सरकारलाई पूर्व जानकारी दिने उद्देश्यले स्थापित रहेको छ । <br /> नेपाल राज्यको स्वतन्त्रता, सार्वभौमसत्ता, भौगोलिक अखण्डता, स्वाधिनताको रक्षा, आन्तरिक एवं राष्ट्रिय सुरक्षा र हितको प्रवर्द्धन एवं सम्वर्द्धन गर्नका निम्ति सरकारलाई आवश्यक पर्ने सबै प्रकारका सूचना उपलव्ध गराउने यो संगठनको जिम्मेवारी हो । राष्ट्रिय सुरक्षाका विभिन्न क्षेत्रका अतिरिक्त आर्थिक एवं वित्तीय अपराध, आतंकवाद, संगठित अपराधलगायतका अपराध, धर्म, सस्कृति, भाषा, समुदायवीचको सद्भावमा खलल पुर्‍याउने पक्षसंग सम्वन्धित सूचना संकलन पनि विभागको महत्वपूर्ण कार्यभार हो । == '''हालसम्मका प्रमुखहरू'''== #रोमबहादुर थापा #पदमबहादुर शाह #धुन्डीराज शर्मा #हर्क बहादुर थापा #रामप्रसाद श्रेष्ठ #चन्दबहादुर राई #लेखबहादुर पाण्डे #विष्णुराज पन्त #गोविन्दकर्म थापा #हरिबाबु चौधरी #देवीराम शर्मा #धनसिंह कार्की #अशोकदेव भट्ट #मोतीबहादुर गुरुङ #जितबहादुर केसी #दिलीपराज रेग्मी #गणेशप्रसाद अधिकारी #यदुलाल खरेल #'''हुतराज थापा''' ==यो पनि हेर्नुहोस्== * [[नेपाली सेना]] * [[नेपाल प्रहरी]] * [[नेपाल सशस्त्र प्रहरी बल|नेपाल ससस्त्र प्रहरी बल]] {{stub}} 8hog0ux5d9rz222rp89fua9vaxem108 1361184 1361183 2026-06-12T01:58:27Z Aayush Dhital 79298 /* हालसम्मका प्रमुखहरू */ 1361184 wikitext text/x-wiki {{Infobox Government agency | agency_name = National Investigation Department | nativename = '''राष्ट्रिय अनुसन्धान विभाग''' | nativename_a = | nativename_r = | logo = | logo_width = | logo_caption = | seal = Emblem_of_Nepal_(alternative).svg | seal_width = 125 px | seal_caption = | formed = वि.सं २००८ | preceding1 = | preceding2 = | dissolved = | superseding = | jurisdiction = नेपाल | headquarters = सिंहदरवार, काठमाण्डौ | employees = | budget = | minister1_name = | minister1_pfo = | minister2_name = | minister2_pfo = | chief1_name = '''टिकेन्द्र कार्की''' | chief1_position = <br /> मुख्य अनुसन्धान निर्देशक | chief2_name = | chief2_position = | parent_agency = प्रधानमन्त्री तथा मन्त्रिपरिषद्को कार्यालय | website = {{URL|nidept.gov.np}} | footnotes = }} '''राष्ट्रिय अनुसन्धान विभाग''' नेपालको संविधानमा व्यवस्था भए वमोजिम संघमा रहने गरी स्थापित इन्टेलिजेन्स संस्था हो । राष्ट्रिय हित एवं सुरक्षाका बारे आवश्यक खबर संकलन गर्ने र संकलित खबरहरुको अध्ययन, मुल्याङ्कन, बिश्लेषण र सम्पादन गरी सरकारलाई पूर्व जानकारी दिने उद्देश्यले स्थापित रहेको छ । <br /> नेपाल राज्यको स्वतन्त्रता, सार्वभौमसत्ता, भौगोलिक अखण्डता, स्वाधिनताको रक्षा, आन्तरिक एवं राष्ट्रिय सुरक्षा र हितको प्रवर्द्धन एवं सम्वर्द्धन गर्नका निम्ति सरकारलाई आवश्यक पर्ने सबै प्रकारका सूचना उपलव्ध गराउने यो संगठनको जिम्मेवारी हो । राष्ट्रिय सुरक्षाका विभिन्न क्षेत्रका अतिरिक्त आर्थिक एवं वित्तीय अपराध, आतंकवाद, संगठित अपराधलगायतका अपराध, धर्म, सस्कृति, भाषा, समुदायवीचको सद्भावमा खलल पुर्‍याउने पक्षसंग सम्वन्धित सूचना संकलन पनि विभागको महत्वपूर्ण कार्यभार हो । == '''हालसम्मका प्रमुखहरू'''== #रोमबहादुर थापा #पदमबहादुर शाह #धुन्डीराज शर्मा #हर्क बहादुर थापा #रामप्रसाद श्रेष्ठ #चन्दबहादुर राई #लेखबहादुर पाण्डे #विष्णुराज पन्त #गोविन्दकर्म थापा #हरिबाबु चौधरी #देवीराम शर्मा #धनसिंह कार्की #अशोकदेव भट्ट #मोतीबहादुर गुरुङ #जितबहादुर केसी #दिलीपराज रेग्मी #गणेशप्रसाद अधिकारी #यदुलाल खरेल #हुतराज थापा #'''टिकेन्द्र कार्की''' ==यो पनि हेर्नुहोस्== * [[नेपाली सेना]] * [[नेपाल प्रहरी]] * [[नेपाल सशस्त्र प्रहरी बल|नेपाल ससस्त्र प्रहरी बल]] {{stub}} e7ti97osdqr9zb24pu6qmgquz6adfuk त्रिभुवन विश्वविद्यालय केन्द्रीय पुस्तकालय 0 7573 1361475 993016 2026-06-12T10:38:24Z Bishaldev100 28807 /* */ 1361475 wikitext text/x-wiki {{Orphan|date=मे २०१३}} [[त्रिभुवन विश्वविद्यालय]] [[कीर्तिपुर नगरपालिका|किर्तिपुर]]मा अवस्थित त्रिवि केन्द्रीय पुस्तकालय देशकै सवभन्दा ठुलो पुस्तकालय हो । यसको स्थापना वि सं २०१६ सालमा भएको हो । जम्मा १२०० सङग्रहबाट सुरूवात भएको यस पुस्तकालयमा हाल ३ लाख ५० हजार भन्दा बढि सङग्रह छन् । त्रिवि केन्द्रीय पुस्तकालयमा रहेका महत्त्वपुर्ण सङग्रहहरू #[[अभिलेख सङ्कलन]] #[[श्रव्य दृश्य सङ्कलन]] #[[साधारण सङ्कलन]] #[[माईक्रोफिल्म सङ्कलन]] #[[नेपाल सङ्कलन]] #[[नेपाली पत्रिका सङ्कलन]] #[[दुर्लभ किताब सङ्कलन]] #[[अनुसन्धान पत्रिका सङ्कलन]] #[[सिंह सङ्कलन]] #[[सन्दर्भ सङ्कलन]] #[[पाठ्यपुस्तक सङ्कलन]] #[[संयुक्त राष्ट्र सङ्घ सामग्री (Depository) सङकलन]] ==सन्दर्भ सामग्रीहरू== {{reflist}} ==बाह्य कडीहरू== [[श्रेणी:नेपालका पुस्तकालयहरू]] {{stub}} 0j994gcbxm4eiako7km29rjxe1mh3w8 1361476 1361475 2026-06-12T10:41:53Z Bishaldev100 28807 1361476 wikitext text/x-wiki {{Orphan|date=मे २०१३}} [[चित्र:Tribhuvan University Central Library.jpg|अङ्गुठाकार|416x416पिक्सेल]] [[त्रिभुवन विश्वविद्यालय]] [[कीर्तिपुर नगरपालिका|किर्तिपुर]]मा अवस्थित त्रिवि केन्द्रीय पुस्तकालय देशकै सवभन्दा ठुलो पुस्तकालय हो । यसको स्थापना वि सं २०१६ सालमा भएको हो । जम्मा १२०० सङग्रहबाट सुरूवात भएको यस पुस्तकालयमा हाल ३ लाख ५० हजार भन्दा बढि सङग्रह छन् । त्रिवि केन्द्रीय पुस्तकालयमा रहेका महत्त्वपुर्ण सङग्रहहरू #[[अभिलेख सङ्कलन]] #[[श्रव्य दृश्य सङ्कलन]] #[[साधारण सङ्कलन]] #[[माईक्रोफिल्म सङ्कलन]] #[[नेपाल सङ्कलन]] #[[नेपाली पत्रिका सङ्कलन]] #[[दुर्लभ किताब सङ्कलन]] #[[अनुसन्धान पत्रिका सङ्कलन]] #[[सिंह सङ्कलन]] #[[सन्दर्भ सङ्कलन]] #[[पाठ्यपुस्तक सङ्कलन]] #[[संयुक्त राष्ट्र सङ्घ सामग्री (Depository) सङकलन]] ==सन्दर्भ सामग्रीहरू== {{reflist}} ==बाह्य कडीहरू== [[श्रेणी:नेपालका पुस्तकालयहरू]] {{stub}} teftf1v4l82qbi8qgjpm4bi8qhblirf 1361477 1361476 2026-06-12T10:42:07Z Bishaldev100 28807 1361477 wikitext text/x-wiki {{Orphan|date=मे २०१३}} [[चित्र:Tribhuvan University Central Library.jpg|अङ्गुठाकार|416x416पिक्सेल|त्रिभुवन विश्वविद्यालय केन्द्रीय पुस्तकालय]] [[त्रिभुवन विश्वविद्यालय]] [[कीर्तिपुर नगरपालिका|किर्तिपुर]]मा अवस्थित त्रिवि केन्द्रीय पुस्तकालय देशकै सवभन्दा ठुलो पुस्तकालय हो । यसको स्थापना वि सं २०१६ सालमा भएको हो । जम्मा १२०० सङग्रहबाट सुरूवात भएको यस पुस्तकालयमा हाल ३ लाख ५० हजार भन्दा बढि सङग्रह छन् । त्रिवि केन्द्रीय पुस्तकालयमा रहेका महत्त्वपुर्ण सङग्रहहरू #[[अभिलेख सङ्कलन]] #[[श्रव्य दृश्य सङ्कलन]] #[[साधारण सङ्कलन]] #[[माईक्रोफिल्म सङ्कलन]] #[[नेपाल सङ्कलन]] #[[नेपाली पत्रिका सङ्कलन]] #[[दुर्लभ किताब सङ्कलन]] #[[अनुसन्धान पत्रिका सङ्कलन]] #[[सिंह सङ्कलन]] #[[सन्दर्भ सङ्कलन]] #[[पाठ्यपुस्तक सङ्कलन]] #[[संयुक्त राष्ट्र सङ्घ सामग्री (Depository) सङकलन]] ==सन्दर्भ सामग्रीहरू== {{reflist}} ==बाह्य कडीहरू== [[श्रेणी:नेपालका पुस्तकालयहरू]] {{stub}} ljojphr9bnczwknh0t4qbtyq2uhm5q6 1361478 1361477 2026-06-12T10:42:54Z Bishaldev100 28807 1361478 wikitext text/x-wiki {{Orphan|date=मे २०१३}} [[चित्र:Tribhuvan University Central Library.jpg|अङ्गुठाकार|416x416पिक्सेल|त्रिभुवन विश्वविद्यालय केन्द्रीय पुस्तकालय]] [[चित्र:TU_Central_Library.jpg|पाठ=TU Central Library Building in 1967|अङ्गुठाकार|TU Central Library Building in 1967]] [[त्रिभुवन विश्वविद्यालय]] [[कीर्तिपुर नगरपालिका|किर्तिपुर]]मा अवस्थित त्रिवि केन्द्रीय पुस्तकालय देशकै सवभन्दा ठुलो पुस्तकालय हो । यसको स्थापना वि सं २०१६ सालमा भएको हो । जम्मा १२०० सङग्रहबाट सुरूवात भएको यस पुस्तकालयमा हाल ३ लाख ५० हजार भन्दा बढि सङग्रह छन् । त्रिवि केन्द्रीय पुस्तकालयमा रहेका महत्त्वपुर्ण सङग्रहहरू #[[अभिलेख सङ्कलन]] #[[श्रव्य दृश्य सङ्कलन]] #[[साधारण सङ्कलन]] #[[माईक्रोफिल्म सङ्कलन]] #[[नेपाल सङ्कलन]] #[[नेपाली पत्रिका सङ्कलन]] #[[दुर्लभ किताब सङ्कलन]] #[[अनुसन्धान पत्रिका सङ्कलन]] #[[सिंह सङ्कलन]] #[[सन्दर्भ सङ्कलन]] #[[पाठ्यपुस्तक सङ्कलन]] #[[संयुक्त राष्ट्र सङ्घ सामग्री (Depository) सङकलन]] ==सन्दर्भ सामग्रीहरू== {{reflist}} ==बाह्य कडीहरू== [[श्रेणी:नेपालका पुस्तकालयहरू]] {{stub}} jakecc5atlwra28ll6rdoowv1qi75xb रुद्रराज पाण्डे 0 9981 1361481 1310008 2026-06-12T10:56:54Z Bishaldev100 28807 1361481 wikitext text/x-wiki {{Distinguish|text=[[रुद्र पाण्डे]], एक नेपाली उद्यमी}}'''रुद्रराज पाण्डे''' नेपाली भाषाका साहित्यकार हुन्। {{Infobox writer | name = रुद्रराज पाण्डे | image = Rudra Raj Pande.jpg | image_size = | alt = | caption = | pseudonym = | birth_name = | birth_date = वि.सं. १९५७, फागुन २६ | birth_place = प्यूखा टोल, [[काठमाडौँ|काठमाडौँ]], नेपाल | death_date = वि.सं. २०४३,चैत २३ | death_place = [[काठमाडौँ|काठमाडौँ]], नेपाल | resting_place = | occupation = लेखक | language = नेपाली | nationality = नेपाली | ethnicity = | citizenship = | education = | alma_mater = | period = | genre = उपन्यास, एकाङ्की | subject = | movement = | notableworks = [[रूपमती (उपन्यास)|रूपमती]] | parents = | spouse = | partner = | children = | relatives = | awards = [[गोरखा दक्षिण बाहु|गो.द.बा. प्रथम]] | religion = | signature = | signature_alt = | module = | website = | portaldisp = }} ==जन्म== *वि सं १९५७ साल फागुन २६ गते काठमाडौँको प्युखा टोल *बाबुको नाम पद्मराज र आमा टिकालक्ष्मी *आमा र बाबु संस्कृतका विज्ञ ==शिक्षा== *घरमै संस्कृतका श्लोकहरू *रानीपोखरी संस्कृत पाठशाला *दरवार हाई स्कूलमा अङ्ग्रेजीको अध्ययन *१८ वर्षको उमेरमा कलकत्ताबाट मेट्रीक पास *भारतको इलाहबादबाट सरकारी खर्चमा [[आई.ए.]],[[बी.ए.]] र इतिहासमा [[एम.ए.]] [[File:Shanti Mishra at the inauguration of the Tribhuvan University Central Library Building at Kirtipur.jpg|thumb|पाण्डे (दायाँबाट चौथो), तत्कालीन प्रधानमन्त्री सूर्यबहादुर थापा र भारतका उपप्रधानमन्त्री मोरारजी देसाईको उपस्थितिमा कीर्तिपुरमा त्रिवि केन्द्रीय पुस्तकालय भवनको उद्घाटनमा]] ==कृतिहरू== === उपन्यास === *[[रूपमती (उपन्यास)|''रूपमती'']] *[[चप्पाकाजी (उपन्यास)|''चप्पाकाजी'']] *''प्रायश्चित्त'' *''प्रेम'' *''हेरफेर'' === कथा सङ्ग्रह === *''नवरत्न'' === एकाङ्की नाटक === *''हाम्रो गौरव'' *''हाम्रो नेपाल'' === अनुवाद === *''इसपनैतिकथा'' === हास्यब्यङ्ग्य === *''नेपाल आजाद सङ्घ उर्फ साँडे सङ्घ'' === धर्म संस्कृति === *''सन्तदर्शन (भाग १)'' *''सन्तदर्शन (भाग २)'' === इतिहास === *''भारतको सङ्क्षिप्त इतिहास (भाग १)'' *''भारतको सङ्क्षिप्त इतिहास (भाग २)'' *''इङ्गल्यान्डको इतिहास'' ==देहावसान== *२०४३ साल चैत २३ [[श्रेणी:खस जाति]] [[श्रेणी:सन् १९०१ मा जन्म]] {{stub}} rbc67padm7far7ugicsx7022b4jamdd 1361482 1361481 2026-06-12T10:57:38Z Bishaldev100 28807 1361482 wikitext text/x-wiki {{Distinguish|text=[[रुद्र पाण्डे]], एक नेपाली उद्यमी}}'''रुद्रराज पाण्डे''' नेपाली भाषाका साहित्यकार हुन्। {{Infobox writer | name = रुद्रराज पाण्डे | image = Rudra Raj Pande.jpg | image_size = | alt = | caption = | pseudonym = | birth_name = | birth_date = वि.सं. १९५७, फागुन २६ | birth_place = प्यूखा टोल, [[काठमाडौँ|काठमाडौँ]], नेपाल | death_date = वि.सं. २०४३,चैत २३ | death_place = [[काठमाडौँ|काठमाडौँ]], नेपाल | resting_place = | occupation = लेखक | language = नेपाली | nationality = नेपाली | ethnicity = | citizenship = | education = | alma_mater = | period = | genre = उपन्यास, एकाङ्की | subject = | movement = | notableworks = [[रूपमती (उपन्यास)|रूपमती]] | parents = | spouse = | partner = | children = | relatives = | awards = [[गोरखा दक्षिण बाहु|गो.द.बा. प्रथम]] | religion = | signature = | signature_alt = | module = | website = | portaldisp = }} ==जन्म== *वि सं १९५७ साल फागुन २६ गते काठमाडौँको प्युखा टोल *बाबुको नाम पद्मराज र आमा टिकालक्ष्मी *आमा र बाबु संस्कृतका विज्ञ ==शिक्षा== *घरमै संस्कृतका श्लोकहरू *रानीपोखरी संस्कृत पाठशाला *दरवार हाई स्कूलमा अङ्ग्रेजीको अध्ययन *१८ वर्षको उमेरमा कलकत्ताबाट मेट्रीक पास *भारतको इलाहबादबाट सरकारी खर्चमा [[आई.ए.]],[[बी.ए.]] र इतिहासमा [[एम.ए.]] [[File:Shanti Mishra at the inauguration of the Tribhuvan University Central Library Building at Kirtipur.jpg|thumb|पाण्डे (दायाँबाट चौथो), तत्कालीन प्रधानमन्त्री [[सूर्यबहादुर थापा]] र भारतका उपप्रधानमन्त्री [[मोरारजी देसाई]]को उपस्थितिमा कीर्तिपुरमा [[त्रिभुवन विश्वविद्यालय केन्द्रीय पुस्तकालय|त्रिवि केन्द्रीय पुस्तकालय]] भवनको उद्घाटनमा]] ==कृतिहरू== === उपन्यास === *[[रूपमती (उपन्यास)|''रूपमती'']] *[[चप्पाकाजी (उपन्यास)|''चप्पाकाजी'']] *''प्रायश्चित्त'' *''प्रेम'' *''हेरफेर'' === कथा सङ्ग्रह === *''नवरत्न'' === एकाङ्की नाटक === *''हाम्रो गौरव'' *''हाम्रो नेपाल'' === अनुवाद === *''इसपनैतिकथा'' === हास्यब्यङ्ग्य === *''नेपाल आजाद सङ्घ उर्फ साँडे सङ्घ'' === धर्म संस्कृति === *''सन्तदर्शन (भाग १)'' *''सन्तदर्शन (भाग २)'' === इतिहास === *''भारतको सङ्क्षिप्त इतिहास (भाग १)'' *''भारतको सङ्क्षिप्त इतिहास (भाग २)'' *''इङ्गल्यान्डको इतिहास'' ==देहावसान== *२०४३ साल चैत २३ [[श्रेणी:खस जाति]] [[श्रेणी:सन् १९०१ मा जन्म]] {{stub}} oxgloattppqiw863u94haukc3nhnizn 1361485 1361482 2026-06-12T11:01:41Z Bishaldev100 28807 1361485 wikitext text/x-wiki {{Distinguish|text=[[रुद्र पाण्डे]], एक नेपाली उद्यमी}}[[सरदार]] '''रुद्रराज पाण्डे''' नेपाली भाषाका एक साहित्यकार, शिक्षाविद्, लेखक र इतिहासकार थिए। उनले १९२५ देखि १९३८ सम्म [[दरबार हाई स्कुल|दरबार हाई स्कूल]]को हेडमास्टर , १९३८ देखि १९५१ सम्म [[त्रि-चन्द्र कलेज]]को हेडमास्टर र १९६४ देखि १९६९ सम्म [[त्रिभुवन विश्वविद्यालय]]को उपकुलपतिको रूपमा सेवा गरेका थिए। उनले [[रूपमती (उपन्यास)|रूपमती]] सहित धेरै उपन्यासहरू लेखेका थिए, जसलाई नेपाली भाषामा लेखिएका प्रारम्भिक उपन्यासहरू मध्ये एक मानिन्छ। उनले [[एसएलसी|एसएलसी परीक्षा बोर्ड]] र [[पुरातत्व विभाग (नेपाल)|पुरातत्व विभाग]] स्थापना गर्न पनि सक्रिय भूमिका खेलेका थिए। {{Infobox writer | name = रुद्रराज पाण्डे | image = Rudra Raj Pande.jpg | image_size = | alt = | caption = | pseudonym = | birth_name = | birth_date = वि.सं. १९५७, फागुन २६ | birth_place = प्यूखा टोल, [[काठमाडौँ|काठमाडौँ]], नेपाल | death_date = वि.सं. २०४३,चैत २३ | death_place = [[काठमाडौँ|काठमाडौँ]], नेपाल | resting_place = | occupation = लेखक | language = नेपाली | nationality = नेपाली | ethnicity = | citizenship = | education = | alma_mater = | period = | genre = उपन्यास, एकाङ्की | subject = | movement = | notableworks = [[रूपमती (उपन्यास)|रूपमती]] | parents = | spouse = | partner = | children = | relatives = | awards = [[गोरखा दक्षिण बाहु|गो.द.बा. प्रथम]] | religion = | signature = | signature_alt = | module = | website = | portaldisp = }} ==जन्म== *वि सं १९५७ साल फागुन २६ गते काठमाडौँको प्युखा टोल *बाबुको नाम पद्मराज र आमा टिकालक्ष्मी *आमा र बाबु संस्कृतका विज्ञ ==शिक्षा== *घरमै संस्कृतका श्लोकहरू *रानीपोखरी संस्कृत पाठशाला *दरवार हाई स्कूलमा अङ्ग्रेजीको अध्ययन *१८ वर्षको उमेरमा कलकत्ताबाट मेट्रीक पास *भारतको इलाहबादबाट सरकारी खर्चमा [[आई.ए.]],[[बी.ए.]] र इतिहासमा [[एम.ए.]] [[File:Shanti Mishra at the inauguration of the Tribhuvan University Central Library Building at Kirtipur.jpg|thumb|तत्कालीन प्रधानमन्त्री [[सूर्यबहादुर थापा]] र भारतका उपप्रधानमन्त्री [[मोरारजी देसाई]]को उपस्थितिमा कीर्तिपुरमा [[त्रिभुवन विश्वविद्यालय केन्द्रीय पुस्तकालय|त्रिवि केन्द्रीय पुस्तकालय]] भवनको उद्घाटनमा उपकुलपति पाण्डे (दायाँबाट चौथो)]] ==कृतिहरू== === उपन्यास === *[[रूपमती (उपन्यास)|''रूपमती'']] *[[चप्पाकाजी (उपन्यास)|''चप्पाकाजी'']] *''प्रायश्चित्त'' *''प्रेम'' *''हेरफेर'' === कथा सङ्ग्रह === *''नवरत्न'' === एकाङ्की नाटक === *''हाम्रो गौरव'' *''हाम्रो नेपाल'' === अनुवाद === *''इसपनैतिकथा'' === हास्यब्यङ्ग्य === *''नेपाल आजाद सङ्घ उर्फ साँडे सङ्घ'' === धर्म संस्कृति === *''सन्तदर्शन (भाग १)'' *''सन्तदर्शन (भाग २)'' === इतिहास === *''भारतको सङ्क्षिप्त इतिहास (भाग १)'' *''भारतको सङ्क्षिप्त इतिहास (भाग २)'' *''इङ्गल्यान्डको इतिहास'' ==देहावसान== *२०४३ साल चैत २३ [[श्रेणी:खस जाति]] [[श्रेणी:सन् १९०१ मा जन्म]] {{stub}} 8yifocrudlmmyahbfqldhvb7zop4594 1361486 1361485 2026-06-12T11:02:46Z Bishaldev100 28807 1361486 wikitext text/x-wiki {{Distinguish|text=[[रुद्र पाण्डे]], एक नेपाली उद्यमी}}[[सरदार]] '''रुद्रराज पाण्डे''' नेपाली भाषाका एक साहित्यकार, शिक्षाविद्, लेखक र इतिहासकार थिए। उनले सन् १९२५ देखि १९३८ सम्म [[दरबार हाई स्कुल|दरबार हाई स्कूल]]को हेडमास्टर , सन् १९३८ देखि १९५१ सम्म [[त्रि-चन्द्र कलेज]]को हेडमास्टर र सन् १९६४ देखि १९६९ सम्म [[त्रिभुवन विश्वविद्यालय]]को उपकुलपतिको रूपमा सेवा गरेका थिए। उनले [[रूपमती (उपन्यास)|रूपमती]] सहित धेरै उपन्यासहरू लेखेका थिए, जसलाई नेपाली भाषामा लेखिएका प्रारम्भिक उपन्यासहरू मध्ये एक मानिन्छ। उनले [[एसएलसी|एसएलसी परीक्षा बोर्ड]] र [[पुरातत्व विभाग (नेपाल)|पुरातत्व विभाग]] स्थापना गर्न पनि सक्रिय भूमिका खेलेका थिए। {{Infobox writer | name = रुद्रराज पाण्डे | image = Rudra Raj Pande.jpg | image_size = | alt = | caption = | pseudonym = | birth_name = | birth_date = वि.सं. १९५७, फागुन २६ | birth_place = प्यूखा टोल, [[काठमाडौँ|काठमाडौँ]], नेपाल | death_date = वि.सं. २०४३,चैत २३ | death_place = [[काठमाडौँ|काठमाडौँ]], नेपाल | resting_place = | occupation = लेखक | language = नेपाली | nationality = नेपाली | ethnicity = | citizenship = | education = | alma_mater = | period = | genre = उपन्यास, एकाङ्की | subject = | movement = | notableworks = [[रूपमती (उपन्यास)|रूपमती]] | parents = | spouse = | partner = | children = | relatives = | awards = [[गोरखा दक्षिण बाहु|गो.द.बा. प्रथम]] | religion = | signature = | signature_alt = | module = | website = | portaldisp = }} ==जन्म== *वि सं १९५७ साल फागुन २६ गते काठमाडौँको प्युखा टोल *बाबुको नाम पद्मराज र आमा टिकालक्ष्मी *आमा र बाबु संस्कृतका विज्ञ ==शिक्षा== *घरमै संस्कृतका श्लोकहरू *रानीपोखरी संस्कृत पाठशाला *दरवार हाई स्कूलमा अङ्ग्रेजीको अध्ययन *१८ वर्षको उमेरमा कलकत्ताबाट मेट्रीक पास *भारतको इलाहबादबाट सरकारी खर्चमा [[आई.ए.]],[[बी.ए.]] र इतिहासमा [[एम.ए.]] [[File:Shanti Mishra at the inauguration of the Tribhuvan University Central Library Building at Kirtipur.jpg|thumb|तत्कालीन प्रधानमन्त्री [[सूर्यबहादुर थापा]] र भारतका उपप्रधानमन्त्री [[मोरारजी देसाई]]को उपस्थितिमा कीर्तिपुरमा [[त्रिभुवन विश्वविद्यालय केन्द्रीय पुस्तकालय|त्रिवि केन्द्रीय पुस्तकालय]] भवनको उद्घाटनमा उपकुलपति पाण्डे (दायाँबाट चौथो)]] ==कृतिहरू== === उपन्यास === *[[रूपमती (उपन्यास)|''रूपमती'']] *[[चप्पाकाजी (उपन्यास)|''चप्पाकाजी'']] *''प्रायश्चित्त'' *''प्रेम'' *''हेरफेर'' === कथा सङ्ग्रह === *''नवरत्न'' === एकाङ्की नाटक === *''हाम्रो गौरव'' *''हाम्रो नेपाल'' === अनुवाद === *''इसपनैतिकथा'' === हास्यब्यङ्ग्य === *''नेपाल आजाद सङ्घ उर्फ साँडे सङ्घ'' === धर्म संस्कृति === *''सन्तदर्शन (भाग १)'' *''सन्तदर्शन (भाग २)'' === इतिहास === *''भारतको सङ्क्षिप्त इतिहास (भाग १)'' *''भारतको सङ्क्षिप्त इतिहास (भाग २)'' *''इङ्गल्यान्डको इतिहास'' ==देहावसान== *२०४३ साल चैत २३ [[श्रेणी:खस जाति]] [[श्रेणी:सन् १९०१ मा जन्म]] {{stub}} fgzg5bg38m1l8uh5jzpkwrctdg520wi 1361487 1361486 2026-06-12T11:04:03Z Bishaldev100 28807 1361487 wikitext text/x-wiki {{Distinguish|text=[[रुद्र पाण्डे]], एक नेपाली उद्यमी}}[[सरदार]] '''रुद्रराज पाण्डे''' नेपाली भाषाका एक साहित्यकार, शिक्षाविद्, लेखक र इतिहासकार थिए।<ref>{{Cite web |last=Magazine |first=New Spolight |title=SARDAR RUDRA RAJ PANDE JAYANTI Remembering Contributions |url=https://www.spotlightnepal.com/2022/03/28/sardar-rudra-raj-pande-jayanti-remembering-contributions/ |access-date=2022-06-10 |website=SpotlightNepal |language=en}}</ref> उनले सन् १९२५ देखि १९३८ सम्म [[दरबार हाई स्कुल|दरबार हाई स्कूल]]को हेडमास्टर , सन् १९३८ देखि १९५१ सम्म [[त्रि-चन्द्र कलेज]]को हेडमास्टर र सन् १९६४ देखि १९६९ सम्म [[त्रिभुवन विश्वविद्यालय]]को उपकुलपतिको रूपमा सेवा गरेका थिए। उनले [[रूपमती (उपन्यास)|रूपमती]] सहित धेरै उपन्यासहरू लेखेका थिए, जसलाई नेपाली भाषामा लेखिएका प्रारम्भिक उपन्यासहरू मध्ये एक मानिन्छ।<ref>{{Cite web |title=१२१औं रुद्रराज पाण्डे जन्मजयन्ती मनाइयो |url=https://ekantipur.com/literature/2021/03/13/161564404132927834.html |access-date=2022-03-26 |website=ekantipur.com |language=ne}}</ref> उनले [[एसएलसी|एसएलसी परीक्षा बोर्ड]] र [[पुरातत्व विभाग (नेपाल)|पुरातत्व विभाग]] स्थापना गर्न पनि सक्रिय भूमिका खेलेका थिए। {{Infobox writer | name = रुद्रराज पाण्डे | image = Rudra Raj Pande.jpg | image_size = | alt = | caption = | pseudonym = | birth_name = | birth_date = वि.सं. १९५७, फागुन २६ | birth_place = प्यूखा टोल, [[काठमाडौँ|काठमाडौँ]], नेपाल | death_date = वि.सं. २०४३,चैत २३ | death_place = [[काठमाडौँ|काठमाडौँ]], नेपाल | resting_place = | occupation = लेखक | language = नेपाली | nationality = नेपाली | ethnicity = | citizenship = | education = | alma_mater = | period = | genre = उपन्यास, एकाङ्की | subject = | movement = | notableworks = [[रूपमती (उपन्यास)|रूपमती]] | parents = | spouse = | partner = | children = | relatives = | awards = [[गोरखा दक्षिण बाहु|गो.द.बा. प्रथम]] | religion = | signature = | signature_alt = | module = | website = | portaldisp = }} ==जन्म== *वि सं १९५७ साल फागुन २६ गते काठमाडौँको प्युखा टोल *बाबुको नाम पद्मराज र आमा टिकालक्ष्मी *आमा र बाबु संस्कृतका विज्ञ ==शिक्षा== *घरमै संस्कृतका श्लोकहरू *रानीपोखरी संस्कृत पाठशाला *दरवार हाई स्कूलमा अङ्ग्रेजीको अध्ययन *१८ वर्षको उमेरमा कलकत्ताबाट मेट्रीक पास *भारतको इलाहबादबाट सरकारी खर्चमा [[आई.ए.]],[[बी.ए.]] र इतिहासमा [[एम.ए.]] [[File:Shanti Mishra at the inauguration of the Tribhuvan University Central Library Building at Kirtipur.jpg|thumb|तत्कालीन प्रधानमन्त्री [[सूर्यबहादुर थापा]] र भारतका उपप्रधानमन्त्री [[मोरारजी देसाई]]को उपस्थितिमा कीर्तिपुरमा [[त्रिभुवन विश्वविद्यालय केन्द्रीय पुस्तकालय|त्रिवि केन्द्रीय पुस्तकालय]] भवनको उद्घाटनमा उपकुलपति पाण्डे (दायाँबाट चौथो)]] ==कृतिहरू== === उपन्यास === *[[रूपमती (उपन्यास)|''रूपमती'']] *[[चप्पाकाजी (उपन्यास)|''चप्पाकाजी'']] *''प्रायश्चित्त'' *''प्रेम'' *''हेरफेर'' === कथा सङ्ग्रह === *''नवरत्न'' === एकाङ्की नाटक === *''हाम्रो गौरव'' *''हाम्रो नेपाल'' === अनुवाद === *''इसपनैतिकथा'' === हास्यब्यङ्ग्य === *''नेपाल आजाद सङ्घ उर्फ साँडे सङ्घ'' === धर्म संस्कृति === *''सन्तदर्शन (भाग १)'' *''सन्तदर्शन (भाग २)'' === इतिहास === *''भारतको सङ्क्षिप्त इतिहास (भाग १)'' *''भारतको सङ्क्षिप्त इतिहास (भाग २)'' *''इङ्गल्यान्डको इतिहास'' ==देहावसान== *२०४३ साल चैत २३ [[श्रेणी:खस जाति]] [[श्रेणी:सन् १९०१ मा जन्म]] {{stub}} mqgrb7bumgcptqj2tq3bdwkv7tfo4yk विश्व खाद्य कार्यक्रम 0 17071 1361197 1149783 2026-06-12T06:04:19Z Bishaldev100 28807 /* सन्दर्भ सामग्रीहरू */ 1361197 wikitext text/x-wiki {{Infobox United Nations | image = Emblem of the United Nations.svg | image_size = 120px | name = विश्व खाद्य कार्यक्रम | map = World Food Programme Logo Simple.svg | map_size = 200 | map_caption = विश्व खाद्य कार्यक्रमको लोगो | type = [[अन्तर-सरकारी सङ्गठन]], [[नियामक निकाय]], [[सल्लाहकार समिति]] | abbreviation = WFP | leader_title = प्रमुख | leader_name = [[डेभिड बास्ले]] | status = सकृय | formation = {{start date and age|1961|12|19|df=yes}} | headquarters = [[रोम]], [[इटाली]] | website = [http://www1.wfp.org www.wfp.org] | parent_organization = [[संयुक्त राष्ट्र महासभा]] | subsidiaries = | footnotes = {{portal-inline|राजनीति|size=tiny}} }} '''विश्व खाद्य कार्यक्रम''' ([[w:en:World Food Programme|World Food Programme]]) (डब्लूएफपी) [[संयुक्त राष्ट्र|संयुक्त राष्ट्र सङ्घ]]को खाद्य सहायता शाखा हो। यो [[भोकमरी]] विरूद्ध सम्बोधन गर्ने संसारकै सबै भन्दा ठूलो मानवीय सङ्गठन हो। यसले खाद्य सुरक्षालाई महत्त्व दिन्छ। यसको मुख्यालय इटालीको [[रोम]]मा छ र ८० भन्दा बढी देशमा यसका कार्यालयहरू रहेका छन्। डब्लूएफपीले काम गर्ने व्यक्ति वा आफैले र परिवारका लागि पर्याप्त खाना प्राप्त गर्न मद्दत पुर्याउँदछ। यो संयुक्त राष्ट्र विकास समूह र यसको कार्यकारी समितिको सदस्य हो। [3] ==उद्देश्य== विश्व खाद्य कार्यक्रमका उद्देश्यहरू निम्नानुसार रहेका छन् <ref>{{cite web |last=विश्व खाद्य कार्यक्रम |title=हाम्रो कार्य |url=http://www.wfp.org/our-work |publisher=WFP |accessdate=२० अगस्त २०१८}}</ref> # "विपदमा प्राण जोगाउनु र जीविकाको संरक्षण गर्नु" # "खाद्य सुरक्षा र पोषणलाई टेवा दिनू र नाजुक अवस्थितिमा रहेका अथवा विपत्तिमा परेका हरूको जीविका (पुन) स्थापित गर्नु" # "जोखिम घटाउनु तथा व्यक्तिऽ समुदाय र राष्ट्रहरूलाई आफ्नै खाद्य तथा पोषण सम्बन्धि आवश्यकता जुटाउन सवलिकरण गर्नु" # "कुपोषण घटाई अन्तर-पुस्ता भोक चक्र रोक्नु" # "सन् २०३० सम्ममा भोक शुन्यमा ल्याउने" ==सन्दर्भ सामग्रीहरू== {{reflist}} {{ढाँचा:२०२० नोबेल पुरस्कार विजेताहरू}} [[श्रेणी:संयुक्त राष्ट्र सङ्घ]] [[श्रेणी:अन्तर्राष्ट्रिय संस्थाहरू]] {{stub}} dqrvagq6qhm3n5pntuf8klyfukqz6vz अर्चले 0 27849 1361177 1291164 2026-06-11T20:25:28Z Sunlightson 66105 1361177 wikitext text/x-wiki {{Infobox settlement <!-- आधारभूत जानकारी --> |name = |other_name = |native_name = |nickname = |settlement_type = पूर्व गाविस |motto = <!-- चित्र र नक्सा--> |image_skyline = |image_caption = |image_flag = |image_seal = |image_map = <!-- NepalPalpaDistrictmap.png --> |mapsize = 300px |map_caption = पाल्पा जिल्लाका गाउँ विकास समितिहरूको नक्सा |pushpin_map = Nepal Lumbini Province#Nepal |pushpin_label_position = bottom |pushpin_mapsize = 300 |pushpin_map_caption = नेपालको नक्सामा {{पृष्ठको नाम}}को अवस्थिति <!-- अवस्थिति --> |subdivision_type = देश |subdivision_name = {{झण्डा|नेपाल}} |subdivision_type1 = [[नेपालका प्रदेशहरू|प्रदेश]] |subdivision_name1 = [[लुम्बिनी प्रदेश]] |subdivision_type2 = [[नेपालका जिल्लाहरू|जिल्ला]] |subdivision_name2 = [[पाल्पा जिल्ला]] <!-- राजनीति --> |government_footnotes = |government_type = |leader_title = |leader_name = |leader_title1 = <!-- for places with, say, both a mayor and a city manager --> |leader_name1 = |established_title = <!-- Settled --> |established_date = <!-- क्षेत्रफल --> |unit_pref = <!--Enter: Imperial, if Imperial (metric) is desired--> |area_footnotes = |area_total_km2 = २३.७७<!-- ALL fields dealing with a measurements are subject to automatic unit conversion--> |area_total_sq_mi = <!-- जनसङ्ख्या --> |population_as_of = [[नेपालको एघारौँ राष्ट्रिय जनगणना, २०६८|वि.सं २०६८]] |population_footnotes = |population_note = |population_total = 9663 |population_density_km2 = auto |population_blank1_title = जातीयता |population_blank2_title = Religions <!-- साधारण जानकारी --> |timezone = [[नेपालको प्रमाणिक समय|नेपाली समय]] |utc_offset = +५:४५ |timezone_DST = |utc_offset_DST = |coordinates = {{coord|27.77|83.85|type:adm2nd_region:NP_source:unmaps-enwiki|display=inline,title}} |elevation_footnotes = <!--for references: use <ref> </ref> tags--> |elevation_m = <!-- Area/postal codes & others --> |postal_code_type = <!-- enter ZIP code, Postcode, Post code, Postal code... --> |postal_code = |area_code = |blank_name = |blank_info = |website = |footnotes = }} '''{{पृष्ठको नाम}}''' [[नेपालको पूर्व प्रशासनिक विभाजन]] अनुसार, [[पश्चिमाञ्चल विकास क्षेत्र|पश्चिमाञ्चल]] विकास क्षेत्रको [[लुम्बिनी अञ्चल]], [[पाल्पा जिल्ला]]मा अवस्थित एक [[गाउँ विकास समिति (नेपाल)|गाविस]] थियो। [[नेपालको एघारौँ राष्ट्रिय जनगणना, २०६८|एघारौँ राष्ट्रिय जनगणना २०६८]]मा यहाँको जनसङ्ख्या ९६६३ रहेको थियो जसमध्ये ४४८० पुरुष र ५१८३ महिला रहेका थिए भने यहाँ १९९२ घरधुरी रहेको थियो।<ref>{{वेब स्रोत|युआरएल=https://cbs.gov.np/wp-content/upLoads/2019/07/pulationandhousing-census-2011.pdf|शीर्षक=राष्ट्रिय जनगणना २०६८| प्रकाशक=[[नेपाल सरकार]] '''केन्द्रिय तथ्याङ्क विभाग'''|प्रारूप=पिडिएफ |कार्य=राष्ट्रिय योजना आयोग सचिवालय}}</ref> यो हाल [[निस्दी गाउँपालिका]]मा पर्दछ। यो निस्दी गाउँपालिकाको वडा नम्बर ६ हो। ==२०१५ नेपाल भूकम्प== गाउँ [[२०१५ अप्रिल २५ को नेपाल भूकम्प|भूकम्प]]बाट प्रभावित भयो। सो क्षेत्रमा आएको रिपोर्टहरू अनुसार भूकम्प पछि गाउँ पूर्ण रूपमा ध्वस्त भएको छ। भूकम्प हुँदा गाउँमा विवाह समारोह भइरहेको थियो। विवाहमा सहभागी पन्ध्र जना पाहुनाहरूको मृत्यु भएको थियो। बाइसवटा घरहरू ध्वस्त भए। अधिकांश ध्वस्त भएका घरहरू माटो, ईँटा र ढुङ्गाबाट बनेका कमजोर घरहरू हुन्। ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} {{ढाँचा:पाल्पा जिल्लाका गाविसहरू}} [[श्रेणी:पाल्पा जिल्लाका ठाउँहरू]] m7otdrucv5xgok9lo4ad7nen5r12ue0 1361178 1361177 2026-06-11T20:26:07Z Sunlightson 66105 1361178 wikitext text/x-wiki {{Infobox settlement <!-- आधारभूत जानकारी --> |name = |other_name = |native_name = |nickname = |settlement_type = पूर्व गाविस |motto = <!-- चित्र र नक्सा--> |image_skyline = |image_caption = |image_flag = |image_seal = |image_map = <!-- NepalPalpaDistrictmap.png --> |mapsize = 300px |map_caption = पाल्पा जिल्लाका गाउँ विकास समितिहरूको नक्सा |pushpin_map = Nepal Lumbini Province#Nepal |pushpin_label_position = bottom |pushpin_mapsize = 300 |pushpin_map_caption = नेपालको नक्सामा {{पृष्ठको नाम}}को अवस्थिति <!-- अवस्थिति --> |subdivision_type = देश |subdivision_name = {{झण्डा|नेपाल}} |subdivision_type1 = [[नेपालका प्रदेशहरू|प्रदेश]] |subdivision_name1 = [[लुम्बिनी प्रदेश]] |subdivision_type2 = [[नेपालका जिल्लाहरू|जिल्ला]] |subdivision_name2 = [[पाल्पा जिल्ला]] <!-- राजनीति --> |government_footnotes = |government_type = |leader_title = |leader_name = |leader_title1 = <!-- for places with, say, both a mayor and a city manager --> |leader_name1 = |established_title = <!-- Settled --> |established_date = <!-- क्षेत्रफल --> |unit_pref = <!--Enter: Imperial, if Imperial (metric) is desired--> |area_footnotes = |area_total_km2 = २३.७७<!-- ALL fields dealing with a measurements are subject to automatic unit conversion--> |area_total_sq_mi = <!-- जनसङ्ख्या --> |population_as_of = [[नेपालको एघारौँ राष्ट्रिय जनगणना, २०६८|वि.सं २०६८]] |population_footnotes = |population_note = |population_total = 9663 |population_density_km2 = auto |population_blank1_title = जातीयता |population_blank2_title = Religions <!-- साधारण जानकारी --> |timezone = [[नेपालको प्रमाणिक समय|नेपाली समय]] |utc_offset = +५:४५ |timezone_DST = |utc_offset_DST = |coordinates = {{coord|27.77|83.85|type:adm2nd_region:NP_source:unmaps-enwiki|display=inline,title}} |elevation_footnotes = <!--for references: use <ref> </ref> tags--> |elevation_m = <!-- Area/postal codes & others --> |postal_code_type = <!-- enter ZIP code, Postcode, Post code, Postal code... --> |postal_code = |area_code = |blank_name = |blank_info = |website = |footnotes = }} '''{{पृष्ठको नाम}}''' [[नेपालको पूर्व प्रशासनिक विभाजन]] अनुसार, [[पश्चिमाञ्चल विकास क्षेत्र|पश्चिमाञ्चल]] विकास क्षेत्रको [[लुम्बिनी अञ्चल]], [[पाल्पा जिल्ला]]मा अवस्थित एक [[गाउँ विकास समिति (नेपाल)|गाविस]] थियो। [[नेपालको एघारौँ राष्ट्रिय जनगणना, २०६८|एघारौँ राष्ट्रिय जनगणना २०६८]]मा यहाँको जनसङ्ख्या ९६६३ रहेको थियो जसमध्ये ४४८० पुरुष र ५१८३ महिला रहेका थिए भने यहाँ १९९२ घरधुरी रहेको थियो।<ref>{{वेब स्रोत|युआरएल=https://cbs.gov.np/wp-content/upLoads/2019/07/pulationandhousing-census-2011.pdf|शीर्षक=राष्ट्रिय जनगणना २०६८| प्रकाशक=[[नेपाल सरकार]] '''केन्द्रिय तथ्याङ्क विभाग'''|प्रारूप=पिडिएफ |कार्य=राष्ट्रिय योजना आयोग सचिवालय}}</ref> यो हाल [[निस्दी गाउँपालिका]]मा पर्दछ। यो निस्दी गाउँपालिकाको वडा नम्बर ६ हो। ==२०१५ नेपाल भूकम्प== गाउँ [[२०१५ अप्रिल २५ को नेपाल भूकम्प|भूकम्प]]बाट प्रभावित भयो। सो क्षेत्रमा आएको रिपोर्टहरू अनुसार भूकम्प पछि गाउँ पूर्ण रूपमा ध्वस्त भएको छ। भूकम्प हुँदा गाउँमा विवाह समारोह भइरहेको थियो। विवाहमा सहभागी पन्ध्र जना पाहुनाहरूको मृत्यु भएको थियो। बाइसवटा घरहरू ध्वस्त भए। अधिकांश ध्वस्त भएका घरहरू माटो, ईँटा र ढुङ्गाबाट बनेका कमजोर घरहरू हुन्।<ref>{{Cite web |url= https://www.telegraph.co.uk/news/worldnews/asia/nepal/11569746/Nepal-earthquake-Inside-Archale-a-village-left-in-ruins.html |title= Nepal earthquake: Inside Archale, a village left in ruins |date= 29 Apr 2015 |accessdate = 1 May 2015 |website= Telegraph.co.uk |last = Freeman |first= Colin |url-status= dead |archiveurl= https://web.archive.org/web/20151026202815/http://www.telegraph.co.uk/news/worldnews/asia/nepal/11569746/Nepal-earthquake-Inside-Archale-a-village-left-in-ruins.html |archivedate= 26 October 2015}}</ref> ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} {{ढाँचा:पाल्पा जिल्लाका गाविसहरू}} [[श्रेणी:पाल्पा जिल्लाका ठाउँहरू]] o0zbiigfd2a0njvxtb7vaenaa6asyjq चीनको सांस्कृतिक क्रान्ति 0 33987 1361170 1319831 2026-06-11T14:06:11Z Bishaldev100 28807 /* */ 1361170 wikitext text/x-wiki [[चित्र:Ahfaz farmers1.jpg|thumb|200px|सांस्कृतिक क्रान्ति]] '''सांस्कृतिक क्रान्ति''' (सरलीकृत चिनियाँ: 无产阶级文化大革命; पारम्परिक चिनियाँ: 無產階級文化大革命, Long form: 'चीनको महान सर्वहारा सांस्कृतिक क्रान्ति' ) [[चीन|जनवादी गणतन्त्र चीन]]मा [[माओ त्सेतुङ|माओ त्से-तुङ]]द्वारा चलाइएको एक सामाजिक-राजनीतिक आन्दोलन थियो सन् १९६६ बाट सुरु भएर सन् १९७६ सम्म चल्यो। माओ ती समय [[चिनियाँ कम्युनिस्ट पार्टी|चीनको कम्युनिस्ट पार्टी]]का अध्यक्ष थिए। १६ मे, १९६६ मा शुरू भएर यो क्रान्ति १० वर्षसम्म चल्यो र यसले [[चीन]]का सामाजिक संरचनामा धेरै ठूलो परिवर्तन गरे। यस क्रान्तिको सुरुवातको घोषणा गर्दै माओ-त्से-तुङले चेतावनी दिएका थिए कि बुर्जुआ वर्ग कम्युनिस्ट पार्टीमा आफ्नो प्रभाव कायम गरेर एक किसिमको तानाशाही स्थापित गर्न चाहन्छ। वास्तवमा सांस्कृतिक क्रान्तिको अभियान माओले आफ्नो पार्टीलाई प्रतिद्वन्द्वीहरूलाई तह लगाउनको लागि शुरू गरेका थिए। यो अवधिमा माओलाई उनकै कान्छी श्रीमती चियाङ चिङ, च्याङ चुङचियाओ, याओ वेङयुआन र वाङ होङवेनले साथ दिएका थिए । यसलाई चिनियाँ सांस्कृतिक क्रान्तिका ‘[[चारजनाको टोली|ग्याङ अफ फोर]]’ पनि भनिन्छ । ==क्रान्ति== सुरुवातमा माओ र तिनका समर्थकहरूले हजारौं रेड गार्डहरूलाई एकजुट गरेर तिनलाई चीनीया समाजका चार पुराना स्तम्भहरू लाई खत्म गर्नको लागि भनियो । यो चार स्तम्भ थिए - पुरानो रिवाज, तौर-तरिका, संस्कृति र पुरानो सोच। "विद्यार्थीहरूले क्रान्तिमा ध्यान दिन सकुन् र क्रान्तिमा लाग्न सकुन्" भनेर कलेजहरूलाई बन्द गरियो र माओले देशभरका छात्रहरूलाई यस क्रान्तिमा अगाडि आउनको लागि आह्वान गरे। यस क्रान्तिले चीनका सामाजिक ढांचालाई निकै क्षति पुर्‍यायो। यस अभियानले लगभग ती सबै चीजहरुमा हमला गर्न शुरू भयो जुन कि साम्यवादका विरोधमा थिए। नतीजा स्वरुप यस सारा क्रान्तिका बेला कयौं मानिसहरू मारिए, हजारौ मानिसहरूलाई बर्बरता र यातनाहरु झेल्न पर्यो। यसले चीनका सांस्कृतिक संरचनालाई धेरै क्षति पुगेको थियो। यस क्रान्तिको दुई वर्ष पछि पनी १९६८ को अन्तसम्म चीन गृहयुद्धको स्थितिमा पुगेको थियो। यसपछि माओले हिंसा रोक्नको लागि रेड गार्डको विलयको घोषणा गरिदिएका थिए। ==प्रारम्भिक चरण (१९६६-६८) == * मे १६ को सूचना * प्रारम्भिक आम र्याली (मे -जुन १९६६) * "मुख्यालयमा बम बर्षाऔ"(जुलाई १९६६) * लाल अगस्ट र सोह्र बुँदा (अगस्ट १९६६) ** चार पुरातनको विनाश * केन्द्रीय कार्य भेला (१९६६ अक्टोबर) * कट्टरपन्थीद्वारा शक्ति कब्जा (१९६७) * राजनैतिक सफाया र "गाउँ फर्क (१९६८) ** बर्ग श्रेणी सफाय (मे-सेप्टेम्बर ) ** गाउँ फर्क (डिसेम्बर १९६८) * माओको व्यक्ति पुजा ==लिन बाओ चरण (१९६९-७१)== * शक्तिको संक्रमणकाल (१९६९ अप्रिल ) * जनमुक्ति सेनाले अग्र भूमिका हासिल (१९७०) ** राष्ट्रपती शासनको पुनर्स्थापना (राज्य अध्यक्ष) * लिन बाओको उडान (१९७१ सेप्टेम्बर) ** मृत्यु (१९७१ सेप्टेम्बर) =="ग्याङ अफ फोर" (१९७२-७६)== {{मुख्य|ग्याङ अफ फोर}} * चाउ एन लाइ र देङको बिरोध (१९७२-७३) ** देङको पुनर्स्थापना र आर्थिक पुनर्निर्माण (१९७५) === चाउ एन लाइको मृत्यु (१९७६ जनवरी)=== १९७६ जनवरी ८, [[जनवादी गणतन्त्र चीनका प्रधानमन्त्री|प्रधानमन्त्री]] [[झोउ एनलाइ|चाउ एन लाई]]को ब्लाडर क्यान्सरको कारणले मृत्यु भयो। जनवरी १५ मा [[देङ सियाओपिङ|देङ शियाओ पिङ]]ले चाउको अन्त्येष्टिमा चाउको आधिकारिक प्रशंसा प्रस्तुत गरे। यस समारोहमा चीनको प्रायः सबै वरिष्ठ नेताहरूको उपस्थिति रहेको थियो तर माओको अनुपस्थिती उल्लेखनीय रह्यो। माओले आलोचना बढ्दै थियो।<ref name=Teiwes>{{cite journal|author1=Frederick Teiwes|author2=Warren Sun|title=The First Tiananmen Incident Revisited: Elite Politics and Crisis Management at the End of the Maoist Era|journal=[[Pacific Affairs]]|year=2004|volume=77|issue=2|jstor=40022499}}</ref>{{rp|217–8}}<ref name=Spence>{{cite book|last=Spence|first=Jonathan|title=The Search for Modern China|publisher=W.W. Norton and Company|year=1999|isbn=0-393-97351-4}}</ref>{{rp|610}} चाउको मृत्यु पछि, माओले न त [[चारजनाको टोली|ग्याङ अफ फो]]को सदस्यलाई प्रधानमन्त्री छने न त देङलाई नै। यसको साटो अलि अपरिचित [[हुआ गोफेङ]]लाई प्रधानमन्त्री नियुक्त गरियो। <ref>{{Cite book|url=https://books.google.com/books?id=tprrCQAAQBAJ&q=after+Zhou's+death,+Mao+selected+neither+a+member+of+the+Gang+of+Four+nor+Deng+Xiaoping+to+become+Premier,+instead+choosing+the+relatively+unknown+Hua+Guofeng.&pg=PT490|title=The Life/Death Rhythms of Capitalist Regimes - Debt Before Dishonour: Timetable of World Dominance 1400-2100|last1=Slatyer|first1=Will|date=2015-02-20|publisher=Partridge Publishing Singapore|isbn=9781482829617|language=en}}</ref> चाउ एन लाइको ठूलो स्तरको लोकप्रियता र समर्थन देखेर [[चारजनाको टोली|ग्याङ अफ फो]] समूह आत्तिन थाले। यसले उनीहरू माथि राजनैतिक आँधी आउन सक्थ्यो। === थ्यानआनमन चोकको घटना (१९७६ अप्रिल)=== === माओको मृत्यु र ग्याङ अफ फोर समूहको गिरफ्तारी (१९७६ सेप्टेम्बर)=== १९७६ सेप्टेम्बर ९ मा माओको मृत्यु भयो। माओको मृत्यु भन्दा केही अघि माओले हुआलाई "तिमीलाई कार्यभारीको रुपमा पाएर, मलाई अहिले सजिलो भएको छ " भन्ने सन्देश लेखेका थिए हुआले यसै सन्देशलाई आफूलाई माओको उत्तराधिकारी प्रमाणित गर्न प्रयोग गरे। हुआलाई राजनैतिक सीप र आकाङ्क्षा नभएको मानिस मानिन्थ्यो र [[चारजनाको टोली|ग्याङ अफ फो]] समूहले उत्तराधिकारीको दौडमा उनलाई खासै ठूलो खतराको रुपमा देखेनन्। अक्टोबर ६ मा, सेना र मार्सल ये जियानयिङको समर्थनमा बिन कुनै ठूलो रक्तपात ग्याङ अफ फो समूहको सबै सदस्यलाई गिरफ्तार गरियो। ==त्यसपछि == * संक्रमणकालीन अवधि * देङ शियाओ पिङ द्वारा सांस्कृतिक क्रान्ति अबैध ठहर == मानवीय सङ्कट == ===मृत्यु === {| class="wikitable" |+सांस्कृतिक क्रान्तिको दौरान मृतक संख्याको अनुमान !क्रम !लेखक किताब !संस्था !प्रकाशित साल !अनुमान !सन्दर्भ |- | |''交锋—当代中国三次思想解放实录'' |प्रेस अफ ''पिपल्स डेली'' |२०११ |२ करोड | |- | |रुडोल्फ जे. रुमेल |युनिभर्सिटी अफ हवाई | |७,७३१,००० | |- | |जुङ च्याङ र जोन हेलिडे | | |कम्तीमा ३० लाख | |- | |चेन युङ-फा |नेसनल ताइवान विश्वविद्यालय | |कम्तीमा १७.२ लाख | |- | |एन्ड्रयु जि. वाल्डर र याङ सु |स्ट्यानफोर्ड विश्वविद्यालय युनिभर्सिटी अफ क्यालिफोर्निया, Irvine | |७.५ लाख- १५ लाख | |- | |डेनियल चिरोट |युनिभर्सिटी अफ वासिङ्टन | |कम्तीमा १० लाख; २ करोड सम्म हुन सक्छ | |- | |मौरिस मेइसनर |युनिभर्सिटी अफ विस्कोन्सिन-मेडिसन | |कम्तीमा ४ लाख | |} ==समीक्षा== माओका यस कदमलाई धेरै जानकार एक ठूलो सामाजिक प्रयोगका गरिमा देख्दछन्। एक यस्तो प्रयोग जसले चीनका पुराना सामाजिक र सांस्कृतिक संरचनालाई उखालेर एक नयाँ चीनको स्थापना गरयो। हुन त धेरै आलोचक यसलाई माओको महात्वाकांक्षाहरूको उपज मान्दछन्। आलोचकहरुका अनुसार माओले यस सांस्कृतिक क्रान्तिको प्रयोग कम्युनिस्ट पार्टीमा आफ्नो विरोधीहरूको सफाया गर्न र सत्तामा आफ्नो अधिकार बनाए राख्नको लागि गरेका थिए। आफ्नो यस प्रयासमा माओ सफल त रहे तर चीनलाई यसको एक ठूलो मूल्य चुकाउनु पर्यो। ==यो पनि हेर्नुहोस्== * [[चीनको जनवादी क्रान्ति]] {{Commonscat|Cultural Revolution}} {{Cold War}} [[श्रेणी:चीनको इतिहास]] [[श्रेणी:चिनियाँ क्रान्तिहरू]] [[श्रेणी:सांस्कृतिक क्रान्ति|सांस्कृतिक क्रान्ति]] izzbbmdh07bvpll3hs3t63047fg4ped प्रयोगकर्ता वार्ता:Rajendra bahadur basnet 3 46859 1361175 1345628 2026-06-11T16:05:54Z ~2026-34443-02 79287 /* खसहरू ले कहिले देखि जनै लगाउन सुरु गरे ? के खसहरूले जनै लगाएको कारण खस सभ्यताको पतन भएको हो ? */ नयाँ खण्ड 1361175 wikitext text/x-wiki {{welcome}} -[[User:RajeshPandey|Rajesh]] ([[User talk:RajeshPandey|वार्ता]]) १७:०७, २० फेब्रुअरी २०१२ (युटिसी(UTC)) == खस जातिय  बस्नेत : गोत्र एक कुल देवता अनेक :राजेन्द्रबहादुर बस्नेत, Tulsipur 6 Dang == खस जातिय  बस्नेत : गोत्र एक कुल देवता अनेक                                                                                             राजेन्द्रबहादुर बस्नेत खस को हुन्? प्राचीन सिंजा राज्यअन्तर्गत बसोबास गर्ने खस जातिले अपनाएको संस्कृति नै मष्टो संस्कृति हो। खस राज्य विशाल भूभागमा फैलिएको थियो। यसमा कश्मीर, कुमाऊँ, तिब्बतको खारी प्रदेश, नेपालको कर्णालीसहितको पश्चिम भूभागदेखि गण्डकी प्रदेशसम्म यसको विस्तार भएको थियो। यसको बारेमा गुइसापे तुची (Giuseppe Tucci) ले आफ्नो पुस्तक Nepal: The Discovery of the Malla मा सिंजाको इतिहासको बारेमा लेखेका छन् — "The Empire of The khas is greater than my country Italy." कर्णाली वारिपारि विकसित भएर फैलिएको खस राज्यको आफ्नै मष्टो संस्कृति र सभ्यता थियो। खसहरूले विकास गरेको मष्टो संस्कृति र यसको प्रारूपको बारेमा उल्लेख गर्नुपूर्व खसहरू को हुन्, यसको बारेमा चर्चा गर्नु उपयुक्त हुन्छ। खसहरूको उद्गम स्थल कहाँ हो र यिनीहरू को हुन् भन्ने बारेमा विभिन्न मतहरू छन्। एउटा मत अनुसार एसिया माइनरबाट विभिन्न समूहहरू बसाइँ सर्ने क्रममा पूर्वतिर सर्दै आएको भन्ने भनाइ छ। अर्को मत उत्तर ध्रुवीय क्षेत्र नजिकबाट बसाइँ सराई गरेर आएको पाइन्छ। त्यसैगरी अर्को मत खसहरूको कश्मीर उद्गम स्थल मान्नेहरू छन्। अर्को महत्त्वपूर्ण मत अनुसार खसहरू टिग्रिस र युफ्रेट्स नदीको किनारमा विकसित मेसोपोटामिया/बेबिलोनियाको सभ्यतासँग जोडिन पुग्छन्। बेबिलोनियामा त्यहाँका प्रख्यात राजा हम्मुरावी (ई.पू. २१२३–२०८०) को शासनकाल पछि उनका उत्तराधिकारीहरू कमजोर हुँदै गएको र करिब ई.पू. १७०० आसपासमा कस्साइट्स (Kassites) ले आक्रमण गरी बेबिलोनियामा कब्जा गरेका थिए। कस्साइट्सहरू उत्तरी पहाडी प्रदेशका बासिन्दाहरू थिए। प्राचीन बेबिलोनियामा (ई.पू. १९९५–११५५) कुसाइटहरू (Kushites) ले राज्य गरेका थिए। तिनै काउस (Kaus), कुसाइट (Kushite), कस्साइट्स (Kassites) बाट खस बनेका हुन् भन्ने मानिन्छ। करिब ई.पू. १००० तिर बेबिलोनियाका कुसाइटहरू पूर्व लागेर विभिन्न ठाउँ हुँदै तिब्बततिर आए, जहाँ उनीहरूले करिब १५० देखि २०० वर्ष शासन गरेको पाइन्छ। यिनीहरू पाँचौँ शताब्दी ईस्वीसम्म तिब्बत र नेपालको कर्णाली क्षेत्रसम्म फैलिएका थिए भन्ने मानिन्छ। सिंजामा तिब्बतको खारी प्रदेशबाट आएका नागराजले शासन गर्नुपूर्व पाल वंशका राजाले राज्य गरेका थिए भन्ने कुरा पूर्णप्रसाद ब्राह्मणले उल्लेख गरेका छन्। ११औँ शताब्दी ईस्वीमा पश्चिम तिब्बत, यारी, खारी, पुराङबाट आएका नागराजले खस राज्यको स्थापना गरेका थिए। ई.पू. १७०० आसपासमा बेबिलोनिया कब्जा गरी लिने कस्साइट्सले मेसोपोटामियामा पहिलोपटक घोडा ल्याएका थिए। घोडचढी गरेर युद्ध गर्दा उनीहरूलाई युद्धमा विजय हासिल गर्न निकै सहज भएको थियो। पछि कस्साइट्सलाई हराएर हिट्टाइट्स (Hittites) ले बेबिलोनियामा शासन गरे। हिट्टाइट्स पछि असीरियनहरूले बेबिलोनियामा शासन गरे। उनीहरू असुर सहर (टिग्रिस नदी किनार) का निवासी थिए। उनीहरूका असुरबनिपाल र सेनाचेरिव प्रसिद्ध राजा थिए। कसै-कसैले तिनै असुरबनिपालसँग 'बान्नी मष्टो' लाई जोड्ने गर्दछन्। असुर प्राचीन असीरियाको धार्मिक राजधानी थियो। प्राचीन मेसोपोटामिया (हालको इराक) को टिग्रिस नदीको पश्चिम किनारमा असुर साम्राज्यको विकास भएको थियो। करिब ई.पू. २६००–२५०० देखि करिब ई.पू. १४०० सम्म यो समृद्ध सहर थियो। असुर यो सहरको मुख्य देवता थिए जो त्यहाँका सबैभन्दा शक्तिशाली र असीरियन साम्राज्यको संरक्षक समेत मानिन्थ्यो। असुरको पुरातात्त्विक सर्वेक्षण जर्मन पुरातत्त्वविद् फ्रेडरिक डिलिच र पछि वाल्टर आन्द्रे (Walter Andrae) ले गरेका थिए। जर्मन ओरिएन्टल सोसाइटीले पनि यसमा कार्य गरेको थियो। यहाँ १६०० भन्दा बढी क्युनिफर्म (Cuneiform) लिपि अंकित माटोका भाँडाहरू भेटिएका छन्। विभिन्न विद्वान्हरूले तिनै असुरबनिपालसँग 'बान्नी मष्टो' लाई जोड्ने गर्दछन्। मेसोपोटामियामा त्यस समयमा विभिन्न देवताहरूको पूजा गरिन्थ्यो। त्यसबेला मुख्य रूपमा इया (Ea), एन-लिल (En-Lil), उतु (Uta), मर्दुक (Marduk) आदि देवताहरूको पूजा गर्ने गरिन्थ्यो। बेबिलोनियाको यसै मर्दुकलाई खसहरूको मुख्य देवता मानेर मर्दुकबाट मष्टो भएको हो भन्ने एकथरी मत पाइन्छ। कतिपयले बेबिलोनियाबाट आएको मष्टो भएकाले यसको नाम 'बाबिरो मष्टो' रहन गएको समेत मान्दछन्। बेबिलोनिया बासीहरू शक्तिका पनि उपासक थिए। उनीहरू इस्तार (Istar) देवीको पूजा गर्दथे। खस जातिहरूले बेबिलोनियामा शासन गर्दा टुर्गु (Turgu) को पूजा गर्दथे। टुर्गु शब्दको अपभ्रंश भएर दुर्गा हुन गएको हो भन्ने मत पनि पाइन्छ। यहाँ विभिन्न देव-देवीका मन्दिरहरू बनेका थिए। सेनाचेरिव (ई.पू. ७०४–६८१) को शासनकालमा मात्र ३४ वटा मन्दिर बनेका थिए। यहाँका प्रमुख राजाहरूमा टिगलाथ-पिलेसर तृतीय, सार्गन द्वितीय, सेनाचेरिव र एसरहडोन प्रमुख थिए। अर्को महान् राजा असुरबनिपाल थिए, तिनै असुरबनिपालबाट बान्नी मष्टो र बेबिलोनियाबाट बाबिरो मष्टो खसहरूमा परम्परागत रूपमा आएको भन्ने मत पनि पाइन्छ। असुर सहरमा बेबिलोनियाको दमन पछि त्यहाँका मानिसहरू (असुर) लाई हेयको दृष्टिले हेरिने र क्रूर रूपमा प्रस्तुत गर्ने र आफूलाई देवत्वकरण गर्ने कार्य उनीहरूले गर्दथे। पछि भारतीय भूभागको तल्लो क्षेत्र (मैदानी क्षेत्र) मा पकड जमाएर सैन्धव सभ्यताको विनाश गर्ने कथित आर्यहरूको समूहले पराजित समूहहरूलाई बेबिलोनियाले असुरहरूमाथि विजय गरेर उनीहरूमाथि विजय गरेको अहङ्कार र असुर शब्दलाई घृणा र हेपाइको रूपमा प्रयोग गरे जस्तै गरेर प्राचीन भारतमा पनि पराजित माथि असुर शब्द त्यसै रूपमा प्रयोग गरेको पाइन्छ र पराजितलाई असुरको आवरण लगाएर आफूलाई देवत्वकरण गरेको पाइन्छ। उनीहरूले साहित्य र शिक्षामा जमाएको पकडले उनीहरूमा यस्तो प्रवृत्ति आयो। खसहरूको बारेमा वैदिक साहित्यमा खासै उल्लेख नहुनु र असुरलाई कतै दानव र कतै देवताको रूपमा उल्लेख गर्नुबाट उनीहरू पहिले खसहरूलाई उपेक्षा मात्र होइन खसले पूजा गर्ने शिवलाई समेत अत्यन्त न्यून कोटीको देवताका रूपमा उल्लेख गरेको पाइन्छ। असुर कुनै दानव नभएर असुर सहरका बासिन्दा थिए। जसको देवताको नाम असुरबाट त्यस सहरको नाम समेत असुर राखिएको थियो। असुर (अस्सूर) प्राचीन मेसोपोटामिया स्थित नव असीरियन साम्राज्यको राजधानी थियो। यसै क्षेत्रमा अहुरमज्दा नामक प्रसिद्ध देवता थिए। प्राचीन इरानी पन्थका यी देवता अहुरमज्दाबाट मज्दाको अपभ्रंश भई मष्टो हुन आएको हो भन्ने एकथरीको मत पाइन्छ। अहुरमज्दालाई संस्कृतमा असुर महत भनेर उल्लेख गरेको छ। पारसी पन्थका संस्थापक जरथुस्त्रले यी देवतालाई अजन्मा, सर्वज्ञ परमेश्वर भनेका छन्। यिनलाई अहुरमज्दा बाहेक ओहरमज्द, होउरमज्द, हुर्मुज, अरमज्द र अज्जन्दार नामबाट पनि चिनिन्छन्। ऋग्वेदमा 'असुर महत' को वर्णन गरेको पाइन्छ। मेसोपोटामियाको सभ्यताको विकासको उत्कर्षको समयमा विभिन्न देव-देवीहरूका मूर्तिहरूको निर्माण र पूजा गर्ने परम्परा विकसित अवस्थामा थियो। यसको प्रारम्भ कहिलेदेखि भयो भन्ने प्रश्नको उत्तर भने अत्यन्तै जटिल छ। सभ्यताको आदिम युगमा जसलाई पाषाण युग भन्ने गरिन्छ, मानिसहरूमा धर्मको भावनाको विकास भएको थिएन। उनीहरूले मानिसको मृत्यु पछि शवलाई त्यत्तिकै छोडेर जान्थे जो पशुपन्छीको आहारा बन्दथ्यो। मध्य पाषाण युगमा आएर शवलाई गाड्ने कार्य प्रारम्भ भएको थियो। विभिन्न उत्खननबाट शवहरूको अस्थिपञ्जरको शिर नजिक राखिएका पाषाण सामग्रीहरूबाट यो कुरा थाहा हुन्छ। यसै युगबाट अन्त्येष्टिमा गरिने अनुष्ठानहरूको प्रारम्भ भएको अनुमान गर्न सकिन्छ। यसैबाट मानिसमा धार्मिक चेतनाको प्रारम्भ भएको अनुमान गर्न सकिन्छ। उत्तर पाषाण युगमा धार्मिक अनुष्ठानको साथसाथै विभिन्न अन्धविश्वासको पनि विकास भएको थियो भन्ने कुरा त्यसबेलाका उत्खननबाट प्राप्त अवशेषहरूबाट थाहा पाउन सकिन्छ। सभ्यताको विकासको साथसाथै मानिसहरू समूहमा बस्ने प्रचलन सुरु भएको थियो। भारतमा गरिएको एउटा अध्ययनले भारतमा सबैभन्दा पहिले 'नेग्रिटो' जातिले बसोबास गरेका थिए। त्यसपछि प्रोटो-अस्ट्रेलोइड वा निषाद आएका थिए। यो जातिको पछि आएका आर्यहरूको संस्कृतिमा विलिन भएको थियो। यी जातिहरू टोटमवादी जातिका थिए। यिनीहरूले नाग, गोही, बाँदर आदिको पूजाको सुरुवात गरेका थिए। भारतमा प्रोटो-अस्ट्रेलोइड जातिले धार्मिक भावनाको सुरुवात गरेका थिए। निषाद पछि द्रविड जाति भारतमा भूमध्य सागरीय क्षेत्रबाट आएका र यिनीहरूले सैन्धव सभ्यता र संस्कृतिको विकास गरेका थिए। सैन्धव धर्मको बारेमा लेख्य सामग्री प्राप्त नभए पनि उत्खननबाट प्राप्त सामग्रीबाट यिनीहरू मातृशक्तिका उपासक थिए। जसमा अनेकौँ नारी मूर्तिहरू समेत प्राप्त भएका छन्। मोहन्जोदारोमा उत्खननबाट एउटा परम पुरुषको कल्पना गरिएको एक मुद्रा जसमा एक नग्न पुरुष योगासन मुद्रामा बसेका छन्। यी योगीका ३ मुख छन् शिरमा शृङ्ग-मुकुट अथवा त्रिशूल अंकित छ। योगीको बायाँतिर एउटा गैँडा र भैँसी र दाहिनेतिर एउटा हात्ती र बाघ छ अगाडि तिर मृग छ। यो आकृति हेर्दा खसहरूसँग शिवलाई जोड्न मिल्ने शैवपाशुपत स्वरूपको यो आकृति देखिन्छ। मार्शलले यसलाई शिवको मुद्रा मानेका छन्। वैदिक आर्यहरू भारतमा आउनु पूर्व विकसित यो सभ्यता र मष्टोलाई शिवसँग जोड्ने मतको आधारमा खस सभ्यताको प्रभाव सैन्धव सभ्यतामा परेको अड्कल गर्न सकिन्छ। खसहरूको उद्गम स्थल बारे विभिन्न विद्वान्हरूका फरक फरक मतहरू छन्। पौराणिक मत अनुसार खस क्षेत्रीहरूको उद्गम थलो हुम्लाको शैपाल र बझाङ थियो भन्ने एकथरीको मान्यता छ। उनीहरू अनुसार खस क्षेत्रीका पुर्खा कैलाशबाट आएको र मष्टोलाई कैलाशमा उत्पन्न भएको र त्यहीँबाट कर्णाली उपत्यकामा आएर अन्यत्र फैलिएको मान्दछन्। इन्डो-आर्यन ओरिजिन थ्योरी (Indo-Aryan Origin Theory) अनुसार हिन्दू साहित्यमा खसहरूको उल्लेख पाइन्छ। आइरिस भाषाविद् सर जी.ए. ग्रियर्सनले आर्य भाषिक हिमालयको तल्लो भागदेखि कश्मीर सम्मका बासिन्दाहरू महाभारतमा उल्लिखित खसका सन्तान हुन् भन्दछन्। इतिहासकार बालकृष्ण शर्मा र नृतत्त्वशास्त्री डोरबहादुर विष्ट खसलाई इन्डो-युरोपियन मूलका मान्दछन्। खसहरू हालको कश्मीरबाट आएका र त्यहाँका स्थानीय खस/कसबाट त्यो ठाउँ कश्मीर रहन गएको मान्दछन्।   करिब ई.पू. २००० तिर खसको एउटा समूह इरानतिर र अर्को समूह सतलज नदीको पूर्वतर्फको पहाडी भागदेखि भेरी नदीसम्म फैलिएर बसे। बालकृष्ण पोखरेल खसलाई वैदिक आर्य मान्दैनन्। उनीहरू पछि गुर्जर, पल्लव, शक जस्तै आर्य बनेका मान्दछन्। आइरिस भाषाशास्त्री जर्ज अब्राहम ग्रियर्सनले खसहरू संस्कृत र इरानी भाषा समूहका आर्य मूलका क्षत्रिय जातिका योद्धाहरू हुन् भन्ने मत राख्दछन्। खसहरूको उद्गमको बारेमा अर्को सशक्त मत झाङ-झुङ (Zhang Zhung) सभ्यतासँग जोडिएको छ। यसलाई झाङ-झुङ सभ्यताको सिद्धान्तको रूपमा चिन्ने गरिन्छ। यो सिद्धान्त अनुसार खसहरूको सम्बन्ध तिब्बतको प्रारम्भिक उद्भव कालदेखि तिब्बती साम्राज्यको उत्थानसम्म खसहरू जोडिएका छन्। कुनै-कुनै वर्णनमा झाङ-झुङ संस्कृति खससँग सम्बन्धित मानिएको छ। केही विवाद पश्चात् खस मल्ल अस्तित्वमा आएका थिए जो तिब्बतबाट पश्चिम नेपालमा आएका मानिन्छन्। किरातहरूको प्रसिद्ध धार्मिक ग्रन्थले खसहरू प्राचीन चीनको तारीम बेसिन (Tarim basin) बाट नेपाल आएका र त्यो बेला नेपालमा किरातहरूको शासन रहेको उल्लेख छ। खसहरूको तारीम बेंसीमा रहेको खसगर (Khasgar) नामक किल्लामा लघु युची कुषाणले आक्रमण गरी त्यहाँबाट भगाएपछि उनीहरू नेपालमा आएको र किराती राजाले त्रिशूली नदीको पश्चिमतिर बसोबास गर्न दिएको र त्यहीँबाट पश्चिम कश्मीरसम्म फैलिएको उल्लेख छ। तिब्बती मान्यतामा पनि खसहरू तिब्बती साम्राज्यसँग जोडिएका थिए। झाङ-झुङ सभ्यता अन्तर्गत यात्से किंगडम (Yaste kingdom) लाई खस/यात्से वा चल्ला/मल्ल वंशको रूपमा चिनिन्थ्यो। कर्णाली प्रदेशमा खस राज्यको स्थापना गर्ने मानिएका नागराज यसै वंशका मानिन्छन्। उनको काल करिब ११औँ शताब्दी मानिन्छ। यात्सेले सन् १२२० तिर जुम्ला र गढवाल विजय गरेको, सन् १२३५–१२३९ बीच गङताङ (Gangtang) माथि विजय हासिल गरेको पाइन्छ। राजा अशोक चल्ल/कल्लले सन् १२५० तिर दक्षिणी सीमा विस्तार गरेका थिए। खसहरूले सन् १२८८ र सन् १३३४ मा काठमाडौँ आक्रमण गरेका थिए। सन् १३२८ पछि पतनोन्मुख भएको खसहरूको राज्य सन् १३७० सम्म पुग्दा पूर्ण रूपमा समाप्त भयो।   खसहरूमा सुरुमा तिब्बती संस्कृतिको ठुलो प्रभाव थियो। खसहरू बसोबास गर्ने सिंजा, जुम्ला, गढवाल र वरिपरिका क्षेत्रहरूमा यसको व्यापक प्रभाव थियो। पछि हिन्दू आर्य शासकहरूको दबदबा बढेको र शासकहरूले पनि उनीहरूका मान्यता अवलम्बन गर्दै गएकाले खसहरूले अवलम्बन गर्दै आएका मान्यताहरूमा क्षयीकरण हुँदै गए। ________________________________________    खसहरूले गुगे नजिकको खसहरूले गुगे नजिकको पाराङमा शासन गर्दथे, पछि तिनीहरू पहिलो र दोस्रो शताब्दीको बीचमा थाक हिमाल र च्याङला  हिमाल को बीचबाट हुम्लामा आएका थिए र त्यहीँ तिनीहरूले पहिलो राज्य स्थापना गरेका थिए।". खस र मष्टो संस्कृति: ऐतिहासिक पृष्ठभूमि प्राचीन सिंजा राज्यको गुगेमा अवस्थित रहेको मल्लवंशका पुर्खाहरू दक्षिण पाराङको पश्चिमी पहाडी क्षेत्रमा राज्य गरेको पाइन्छ, जसको ल्हासा राजपरिवारसँग सम्बन्ध रहेको थियो। पछि गुगेले आफूलाई स्वतन्त्र गरेको थियो। त्यहाँका शासकहरूमध्ये नागदेव र उनका पुत्र कपिललाई खस (Yatse) वंशको संस्थापक मानिन्छ। तिब्बती मूलका भए तापनि नेपालमा आउँदा हिन्दू-आर्य तथा बौद्ध दुवै संस्कृतिको प्रभावले यिनीहरूको जीवनशैली प्रभावित थियो। खसहरूले गुगे नजिकैको पुराङमा शासन गर्दथे। पछि उनीहरू पहिलो र दोस्रो शताब्दीको बीचमा थाक हिमाल र च्याङ्गला हिमालको बीचबाट हुम्लामा आएका थिए र त्यहीँ उनीहरूले पहिलो राज्य स्थापना गरेका थिए। त्यसभन्दा पहिले यिनीहरूले चीनको तारिम उपत्यकामा खसगर (Khasgar) राज्यको स्थापना गरे। त्यसपछि ताक्लाकोटमा आफ्नो कब्जा गरे। खसहरूको उद्गमको सन्दर्भमा अर्को मत अनुसार खसहरू 'शक' जातिबाट आएका हुन् भन्ने छ। राहुल सांकृत्यायन खस र शकलाई एउटै जातिका दुई समूह मान्दछन्। शकहरू ई.पू. को पहिलो शताब्दी पहिले नै आएको र खसहरू हिमाली क्षेत्रतर्फ फैलिएको मानिन्छ। ओमचन्द्र हण्डा लगायत कतिपय विद्वान् यसै सिद्धान्तका पक्षधर छन्। दैलेखको संवत् १०३८ (९८१ ई.) को पहिलो नेपाली भाषाको शिलालेखबाट १००० ई.पू. देखि ५०० ई.पू. सम्म खसहरू नेपालमा आइसकेका थिए भन्ने अनुमान गर्न सकिन्छ। खसहरूको समृद्ध राजनीतिक र नगर सभ्यताको उत्कृष्ट चरण बेबिलोनियामा जुन समयमा कस्साइटहरूको शासन चलिरहेको थियो (१५९५–११५५ ई.पू.), त्यसै समयमा अर्थात् करिब १५०० ई.पू.–६०० ई.पू. (जसलाई वैदिक काल भनिन्छ), खसहरूको विभिन्न समूह बेबिलोनिया क्षेत्रबाट नयाँ ठाउँहरूमा समूह-समूहमा फैलिएर अगाडि गइरहेका थिए। तीमध्येकै एउटा ठुलो समूह इरान, अफगानिस्तान, कश्मीर हुँदै भारतको मैदानी भूभागतर्फ अगाडि बढ्यो। त्यो समूहले आर्य संस्कृतिको विकास गर्यो, वैदिक मन्त्रको रचना गर्यो, आख्यान र उपनिषद्हरूको रचना गर्यो; त्यो समूहले आफूलाई वैदिक आर्यको रूपमा स्थापित गर्यो। ६०० ई.पू. देखि २०० ई.पू. सम्म आउँदा दर्शन, उपनिषद्को रचना, रामायण र महाभारतबाट मानिस र देवताका सम्मानित विचारहरू र विरचित कृतिहरू रचिए। विभिन्न धार्मिक विचार र सम्प्रदाय (बौद्ध, जैन, वैष्णव) अस्तित्वमा आए। २०० ई.पू. बाट मौखिक कुरालाई सम्झन गाह्रो हुने भएकाले यसलाई संक्षिप्त रूपमा बुझ्नका लागि सूत्र रचनाको प्रारम्भ भयो। त्यसका लागि टीका र २०० ई.पू. पश्चात् विभिन्न दर्शन सूत्र, ग्रन्थ भाष्य टीका रचना भए र धार्मिक आन्दोलनले समाजमा ठुलो प्रभाव छोड्न गयो। हरिभद्रको 'षड्दर्शन समुच्चय' छैटौँ शताब्दीमा, समन्तभद्रले 'आप्तमीमांसा', बौद्ध दर्शनका विद्वान् आचार्य भावविवेकले मीमांसा, सांख्य, वैशेषिक र वेदान्तको आलोचना गरिएको 'तर्क ज्वाला' को रचना गरे। १४औँ शताब्दीतिर बौद्ध धर्मको अत्यधिक प्रभाव र वैदिक धर्मप्रतिको प्रहारबाट त्यसलाई बचाउन शंकराचार्य आक्रामक रूपमा अगाडि आए र उनले 'सर्व सिद्धान्त सार संग्रह' नामक पुस्तकको रचना गरे। इरान, अफगानिस्तान, कश्मीर हुँदै भारतको समथर भूभागतर्फ नगएर अफगानिस्तान, कश्मीर हुँदै हिमालयको काख हुँदै पूर्व नेपाली भूभागतर्फ फैलिएको खस (कस्साइट्सको शाखा) आफ्नो आदिम रीतिथिति, संस्कृति र मूल्यमान्यतामा निरन्तर लागिरह्यो। त्यही समूह खस जाति थियो। यिनीहरू बेबिलोनिया र असुर सहरमा विकसित सभ्यता र देवताको विरासत साथै कालान्तरमा बौद्ध संस्कृति तथा धार्मिक प्रभावका कारण खसहरूको संस्कृतिमाथि वैदिक खस आर्यको अपहेलित व्यवहार र आफूलाई श्रेष्ठ ठहर्याउने दम्भका कारण खसहरूका देवता मष्टोलाई उनीहरूले देवताको स्थान नदिएको र वेद तथा उपनिषद्हरूमा कतै उल्लेख नगरेको कुराबाट स्पष्ट हुन्छ। त्यति मात्र होइन, शिव सम्भवतः अवैदिक खसका देवता हुन् जसलाई सैन्धव सभ्यतामा अपनाएर एउटा महत्त्वपूर्ण देवताको रूपमा स्वीकार गरिएको शैव पाशुपताकृति युक्त सामग्री प्राप्त छ। वैदिक साहित्यमा शिवलाई तल्लो दर्जाको महत्त्वहीन देवताको रूपमा देखाइएको छ। पछि वैदिक संस्कृतिमाथि चारैतिरबाट प्रहार भएपछि खसहरूसँग वैदिक खसहरू पराजित भए र खसहरूलाई क्षत्रीयको श्रेणी र सर्वशक्तिमान् देवताको रूपमा शिवलाई मान्यता प्राप्त भएको मानिन्छ। शंकराचार्यको उदयपछि (१४औँ शताब्दी पछि) नेपाली तथा उत्तराखण्ड, कुमाऊँ र कश्मीरका क्षेत्रमा फैलिएका खसहरूको अहिले सम्म पनि आफ्नै समृद्ध मष्टो परम्परा र संस्कृतिमाथि ठुलो प्रहार गरियो र खस पहिचान मास्ने प्रयास गरियो। 'खस' शब्द नै अपमानित शब्दको रूपमा प्रचार गर्न सुरु गरियो। खसहरू पनि बिस्तारै वैदिक खस आर्यहरूका धार्मिक, सांस्कृतिक र सामाजिक व्यवहार अवलम्बन गर्दै आफ्ना आदिम युगदेखि सञ्चित गरेर जोगाएका परम्परा छोड्दै गए र नयाँ व्यवहारहरू अवलम्बन गर्न थाले। डा. हरिश लखेडाले संविधानमा अहिले बाहुन, क्षेत्री, ठकुरी, संन्यासीलाई नेपालमा 'खस आर्य' मा सूचीकृत गरिएको बताउँछन्। People of Nepal का लेखक डोरबहादुर विष्टले दलितहरूलाई पनि खस हुन् भनेका छन्। कामी, दमाई, सार्कीहरूले पनि मष्टो देवताको पूजा गर्दछन्। डा. विपिन अधिकारीले नेपालमा अहिलेका क्षेत्री, बाहुन, कामी, ठकुरी, सार्की, संन्यासी, बादी, दमाई, गाईने र अन्य खसमा पर्दछन् भन्दछन्। इतिहासकार बालकृष्ण शर्मा र डोरबहादुर विष्ट खस/कसलाई युझी मूलका मान्दछन्। इतिहासकार बाबुराम आचार्य खस ऐरावतको एउटा उपशाखा (कविला) हो जसको उत्पत्ति इडावर्त हालको कश्मीरबाट भएको मान्दछन्। खसहरू तेस्रो शताब्दी ई.पू. मा इडावर्तमा रहन्थे। खसको मूल अर्थ 'राजा' वा 'क्षेत्री' अर्थात् 'योद्धा' भन्ने हुन्छ। उनीहरूको बसोबासको स्थल 'खस' बाट कश्मीर रहेको र दोस्रो शताब्दी ई.पू. मा खसको एउटा समूह कजाकिस्तान र अर्को समूह सतलज नदीको पूर्व हुँदै नेपालतर्फ गयो। बालकृष्ण पोखरेल खसहरूलाई वैदिक आर्य मान्दैनन्। प्रा.डा. गोविन्द सिंहले खसहरूमा विधवा विवाह प्रचलित थियो भन्ने मान्यता राख्दछन्। उनीहरूमा खुला समाज थियो। स्त्रीको उच्च स्थान थियो। खसको आर्यको जस्तो जकडन र बन्धनमा बाँधिएको समाज थिएन भन्ने कुराको उल्लेख गरेका छन्। बस्नेत को हुन्? माथि उल्लिखित खसहरूका विभिन्न समूहहरू जो स-साना समूहमा नेपालको पश्चिमी पहाडी क्षेत्रमा फैलिएको हिमालयको काखमा अवस्थित भूभागमा बस्ने खसहरूको एउटा समूह बस्नेत हो। आदिकालदेखि आफ्नै शौर्य, पराक्रम, वीरतापूर्ण र गौरवशाली इतिहास बनाउन सफल भएका कारण बस्नेतहरू इतिहासका विभिन्न कालखण्डदेखि नेपालको एकीकरणको लागि युद्धका मैदानमा अभूतपूर्व उत्साह र साहसले इतिहासमा स्वर्ण अक्षरमा नाम अंकित गर्न सफल जाति हुन्। राजा-रजौटा र राज्य सञ्चालनका प्रमुख जिम्मेवारीहरूका लागि बस्नेत सधैँ नै राज्यको सुरक्षा र सञ्चालनको निम्ति अनिवार्य जस्तै भूमिकामा रहे। "खप्तडी बस्नेतको मूल थलो खप्तड लेक (खेचराद्री) बडीमालिका पश्चिमपट्टी सेती अञ्चलमा अछाम, बझाङ, बाजुरा, थलारा, दार्चुला, बैतडी, डोटीको माझ पूर्व-पश्चिम लम्बायमान अवस्थामा रहेको स्थान हाल मानव विहीन छ। खप्तडी बस्न्यातको अवस्थन खप्तड (खेचराद्री) सेती अञ्चल बडीमालिकाको दायाँ पट्टी छ" भन्ने कुरा योगी नरहरिनाथले बताउनुभएको छ। खप्तड लेकतिर मोटो खालको भुईँमा कालो छिट्का मिसिएको मोटो टुप्पा मसङ्ग्रिँदै गएको निगालो बाँस प्रशस्त पाइने र त्यहीँको नेटो (डाँडाको सिरान) अर्थात् बाँस पाइने नेटो "बाँसनेटो" मा बस्ने मानिसलाई बाँसनेटो — बासनेता — बस्न्याता — बस्न्यात — बस्नेत भएर बस्नेत भएको हुन सक्दछ। आजभोलि पनि गाउँघरमा यस्ता प्रशस्त उदाहरण पाइन्छ, जस्तै: तुलसीपुरबाट बसाइँ सरेर आएको तुलसीपुरे, दैलेखबाट आएको दैलेखी, सल्यानबाट आएको सल्यानी आदि। मध्यकालीन राज्य व्यवस्थामा दरबार सम्बन्धी मुद्दामामिला हेर्ने, बस्ती बसाउने र व्यवस्थित गर्ने जिम्मेवारी पाएको मानिसलाई 'बस्नेत' भन्ने गरिन्थ्यो भन्ने मत तथ्यको नजिक लाग्छ। यसको कारण बस्नेत थरका मानिसहरूको गोत्र एउटै नहुनु पनि हो। खप्तडी बस्नेतको गोत्र कौशिक, श्रीपाली बस्नेतको गोत्र भारद्वाज, खुलाल बस्नेतको गोत्र धनञ्जय र लामिछाने बस्नेतको गोत्र गर्ग हुनाले बस्नेत जातीय भन्दा पदिय उपाधि थियो, जो विभिन्न थर र गोत्रका मानिसहरूलाई कार्यदक्षता, योग्यता र जिम्मेवारी वहन गर्न सक्ने क्षमताको आधारमा प्रदान गर्ने गरिन्थ्यो भन्ने अनुमान गर्न सकिन्छ। श्रीपाली बस्नेतहरूले आफ्ना पुर्खाहरू श्रीपाल राज्यका श्रीपुर शाहीका वंशज मान्दछन्, जसबाट विभिन्न थर र गोत्रका मानिसहरू बस्नेत उपाधिबाट विभूषित भएको र कालान्तरमा विभिन्न थर र गोत्रका मानिस बस्नेत भएको हुन सक्छ भन्न सकिन्छ। खप्तडी बस्नेतको कुलदेवता दाह्रेमष्टो, श्रीपाली बस्नेतको कुलदेवता आदि मष्टो लिसिसाँकोटी, खुलाल बस्नेतको कुलदेवता दाह्रेमष्टो र लामिछाने बस्नेतहरू मध्य भोजपुरको अघेरीतिर कैलाशमष्टो मान्दछन् भने तेह्रथुमतिरका लामिछाने बस्नेतहरू महामष्टो कुलदेवता मान्ने गर्दछन्। मष्टो को हुन्? मष्टो सिंजा साम्राज्य अन्तर्गतका खस जातिले आफ्नो कुलदेवताको रूपमा पूजा-आराधना गर्दै आएका देवता हुन्। प्राचीन सिंजा राज्य अन्तर्गतका क्षेत्री, बाहुन, ठकुरी लगायत कतिपय अन्य जातिका कुलदेवता मष्टो हुन्। तत्कालीन सिंजा राज्य नेपाल खाल्डोदेखि कश्मीर, कुमाऊँ, तिब्बतको खारी सम्म फैलिएको थियो। मष्टो सम्बन्धी विभिन्न मतहरू छन्। मष्टोका विभिन्न भेदहरू पनि छन्। मुख्य रूपमा मष्टो २ किसिमका छन्: १. दाह्रे मष्टो २. दुधे मष्टो मष्टोको पूजा घरमाण्डौ र वनमाण्डौमा गरिन्छ। घरमाण्डौमा मूल धामी बस्ने स्थान जसलाई 'गादी' भनिन्छ, त्यसमा सेतो कपडा लगाएका झाँक्री, चमर, सोँटा सहित मष्टोको थानमा धामी गएपछि देउता चढ्दछन् र उनीहरू काँप्न थाल्दछन्। पश्चिम नेपालको हिमाली क्षेत्र 'जडान' र पहाडी क्षेत्र 'खसान' को नामले चिनिन्छ। यही खसान क्षेत्रमा खस भाषा र मष्टो संस्कृतिको विकास भएको मानिन्छ। तत्कालीन खस देशमा बस्ने बाहुनहरूको कुलदेवता मष्टो हुन्। भारतमा मुसलमान आक्रमण पछि भागेर नेपाल प्रवेश गरेका र हुकुमी शासन कालमा हुकुम प्रमाङ्गीबाट खस बनेका खसहरूको कुलदेवता मष्टो हुँदैनन् भन्ने कुरा डा. जगमान गुरुङ मान्दछन्। उनको अनुसार सम्पूर्ण खसहरूका कुलदेवता मष्टो हुन्। मष्टोका पिता-माता को हुन् भन्ने उल्लेख कतै पाइँदैन। मुगुतिर एउटा किंवदन्ती प्रचलित छ। उक्त मत अनुसार मष्टोको उत्पत्ति कैलाश मानसरोवर क्षेत्रमा भएको थियो। महिषासुर राक्षसले तपस्या गरी ब्रह्माजीलाई रिझाएर पुरुषको हातबाट नमर्ने वरदान मागेको र वरदान पाएपछि देवताहरूलाई पराजित गरी इन्द्रपुत्रलाई पराजित गर्न पिछा गर्दा उनी भागेर हिमवत् खण्ड आउँदा मष्टोदेवको जन्म भएको थियो। कोही-कोहीले मष्टोलाई भगवान् शिवको अंशको रूपमा पनि हेर्ने गर्दछन् र १२ मष्टोका मूल स्थानमा शिवलिङ्गको स्वरूपको अवस्थितिले समेत उक्त कुरालाई औचित्यपूर्ण ठहर्याउने प्रयास गरिन्छ। अर्को मत अनुसार मष्टोलाई स्वर्गका राजा इन्द्रका पुत्र मान्ने गरिन्छ। "स्वर्गका राजा इन्द्र, धर्तीका राजा मष्टो, पातालका राजा नागराज" भन्ने उक्ति प्रचलित छ। मष्टो निराकार हुन्छन्। मष्टो शब्दको उत्पत्ति 'मस्तक' (शिर) बाट भएको योगी नरहरिनाथले मान्दछन्। उनले सुरुमा मष्टो एउटै भएको र पछि मष्टो देवता थपिँदै जाँदा बाह्र मष्टो भन्न थालिएको र बाह्र मष्टोलाई पछि वराह मष्टो, वारामष्टो समेत भन्ने गरिएको थियो। मष्टोको वाहन घोडा हो। भेडा, चितुवा र झार पनि मष्टोका वाहन हुन्। मेसोपोटामियाको मुख्य देवता Marduk (मर्डुक) बाट मष्टो भएको र मेसोपोटामिया स्थित नव-असीरियन साम्राज्यको राजधानी असुरमा स्थित तत्कालीन विख्यात देवता अहुरमज्दाको 'मज्दा' को अपभ्रंश भएर मष्टो भएको भन्ने मत छ। करिब १७०० ई.पू. तिर पहिलोपटक मेसोपोटामियामा घोडा ल्याएर आक्रमण गरी त्यहाँ विजयी भएर शासन गर्ने कस्साइट्स (खस) र उनीहरूको वाहन घोडा र कस/खसको देवता अहुरमज्दाबाट मष्टो बनेका देवताको वाहन घोडा हुनु संयोग मात्र नभई कस्साइट्सबाट खस र अहुरमज्दाबाट मष्टोको निकट र निरन्तरताको सम्बन्ध देखिन्छ। वैदिक सनातन धर्मको विकास हुनुपूर्व नै नेपालमा मष्टो धर्मको विकास भइरहेको भए तापनि हालसम्म मष्टो धर्मको विषयमा कुनै पनि प्राचीन हस्तलिखित सामग्रीहरू प्राप्त भएका छैनन्। तर मष्टो धर्म, देवता र यसको उत्पत्तिका सन्दर्भमा विभिन्न किंवदन्ती, मिथक र कहावतहरू भने प्रशस्त रूपमा पाइन्छन्। प्राचीन बेबिलोनिया/मेसोपोटामियामा मष्टोको पूर्व रूपलाई 'अहुरमज्दा' भनिन्छ र मष्टो धर्म मान्ने प्रथम व्यक्ति आदिमनाथ हुन्। आदिमनाथलाई आदिनाथ भनिन्छ। भगवान् शिवले अलकापुरी शक्तसिंह (बहादुर) लाई दिए र उनै शक्तसिंह देवताका राजा इन्द्र तथा मष्टो भए भन्ने एउटा मत पनि छ। 'मरुत' शब्दको अर्थ वायु हुन्छ, यिनै वायु देवता मरुतबाट मरुत—मउत—मष्ट हुँदै मष्टो भएको भन्ने भनाइ पनि पाइन्छ। मान्छेले मान्ने देवता भएकाले मान्ठ, मान्ठा, मन्ठा हुँदै मष्टो भएको अनुमान सत्यमोहन जोशीको छ। योगी नरहरिनाथले मष्टोलाई महेश्वरको अंश अवतार/अष्टमूर्ति महादेव शिव (पृथ्वी, जल, तेज, वायु, आकाश, चन्द्र, सूर्य र आत्मा) महा+अष्ट भुजी— महाअष्ट, महाष्ट हुँदै मष्टो भएको अड्कल गर्दछन्। मष्टोलाई निराकार बाल ब्रह्मचारी देवता मानिन्छ। पितृ स्वरूपमा वायु, प्रकृतिका स्वरूपमा लिङ्गो, ध्वजा, पताका, रक्षा सूचक हतियार आदि थापेर पूजा गरिन्छ। विक्रम संवत्को पाँचौँ शताब्दीतिर बझाङका राजा सैपाल थापाको समयमा मष्टोले राजकीय मान्यता पाएको थियो भन्ने गरिन्छ। तर लेख्य प्रमाण सन् १४५७ सुरती शाहले जारी गरेको एउटा अभिलेखमा पहिलो पल्ट मष्टो शब्दको उल्लेख गरेकाले यो नै सर्वाधिक प्राचीन मष्टो शब्द उल्लिखित अहिलेसम्मको प्रामाणिक अभिलेख मानिन्छ। खसहरूले मानी आएको मष्टो देवतालाई आर्य जातिले वेद, पुराणमा कतै उल्लेख नगरेकाले खसहरू आर्य नै हुन् भनेर मान्ने आधार नभएको एकथरी मत छ। अथर्ववेदमा खसहरूले मान्ने शिवलाई 'व्रात्य' भनेर हेपिएको र उनका अनुयायी खस जातिलाई 'व्रात्य जाति' भनेर खसालिएको छ। व्रात्य भनेको उपनयन वा यज्ञोपवीत संस्कार नगर्ने, अनार्य, वैदिक कृत्य आदि गर्ने अधिकार नभएको, जसको दश संस्कार हुँदैन भन्ने हो। आर्यका दुई समूहहरू बीचको वैमनस्यताले वा उनीहरूलाई चुनौती दिने आदिवासीहरूसँगको टकरावले यस्तो स्थिति आएको हुन सक्छ। वैष्णवहरूको वर्णाश्रम व्यवस्थालाई नमनेका हुनाले खसहरू र उनले मान्ने देवता शिवलाई व्रात्य भनेको हुनुपर्छ। आफूलाई ठुलो देखाउने र अरूलाई होच्याउने रूपमा आफूलाई देव खलक र अरूलाई राक्षस खलक भनेको हुनुपर्छ। राम्रो काम गर्ने आदर्शवान् व्यक्तिलाई देवता र अरूलाई दुःख दिनेलाई राक्षस भन्ने गरिन्छ। जरथुस्त्र धर्मग्रन्थको देवतालाई "असुर" र राक्षसलाई "दइव" भनिएको छ। ऋग्वेदमा असुर शब्दलाई १५ पल्ट नराम्रो र ९० पल्ट राम्रो अर्थमा प्रयोग गरिएको छ। असुर देवता र असुर सहरको बारेमा यसै आलेखमा अगाडि पनि उल्लेख गरिएको छ। मनुस्मृति तथा महाभारतमा उल्लेख गरिएका झल्ल, मल्ल, नट, करण, खस र द्रविडहरूलाई पाप योनिबाट जन्मिएका धर्मच्युत, व्रात्य जाति भनेर हेपेको पाइन्छ। यक्ष जातिलाई खस, चीन तथा मंगोल जातिलाई दरद र पिशाच, किरात जातिलाई किन्नर र द्रविडलाई बाहिक जाति भनेर हेपेको पाइन्छ। भारतको राजस्थानमा मष्टोलाई मामा देव, पहाडमा मामा ज्यू भन्दछन्। पिथौरागढमा चण्डक मष्टोको मन्दिर छ। बद्रीनाथमा मष्टोलाई घण्टाकर्ण देवता भनेर पूजा गर्छन्। दार्चुला-बैतडीतिर भूमिराज भनेर पूजा गर्छन्। लेखक तेज कार्कीले मष्टो प्रकृति पूजा (Shamanism) वा जडवाद (Animism) नै सर्वप्राचीन आध्यात्मिक चिन्तन भएको र मष्टो संस्कृति यही प्रकृति पूजक भएकाले यसको प्राचीनताको पुष्टि गर्न मिल्ने भाव व्यक्त गर्दछन्। मानव जातिले ३० हजार वर्षदेखि धर्म व्यापार र सामाजिक विभेदीकरण गर्न सिकेको नोआ हरारीको मत लेखक कार्कीले उल्लेख गरेका छन्। करिब ३२ हजार वर्ष पुरानो जर्मनीको स्टे डेल गुफामा भेटिएको सिंह मानव (पुरुष वा महिला) नै पहिलो धार्मिक चिह्न भएको (Harari, Yuval Noah (2015), Sapiens: A Brief History of Humankind, London: Vintage, P. 23/25) मान्दछन्। प्रकृति पूजाको प्रारम्भ साइबेरिया र मध्य एसियाबाट करिब २० हजार वर्ष पहिलेदेखि भएको र मष्टो परम्परा पनि प्रकृति पूजामा आधारित अत्यन्त प्राचीन परम्परा भएको सम्भवतः प्राग-ऐतिहासिक कालदेखि नै सुरु भएको मान्यता छ। मष्टोको प्रादुर्भाव खसहरूका पुर्खाहरूले बेबिलोनियामा शासन गरेको समयमा भएको मान्यता एकथरीको छ। विभिन्न मष्टोहरूका विभिन्न थानहरू हुन्छन्। खोला, किनार, रूखमुनि यिनका थान हुन्छन्। यिनीहरू डरलाग्दा, मानिसहरूलाई दुःख दिने, चाँडै रिसाउने स्वभावका हुन्छन्। ढँडार मष्टोका थान खोल/ढेल्यो र घाई, दुगे। बदु मष्टोका थान कुटासिली र छरिढुस्के, थापा मष्टोको थान घोडा, मौल्याल, गुम्देव, गाईगोठ्या आदि हुन्। नेपालमा मष्टो देवताको सुरुवात कहिले, कसरी र कहाँ भएको थियो भन्ने सन्दर्भमा विभिन्न अड्कल, आख्यान, किंवदन्तीहरू प्रचलित छन्। विभिन्न मत तथा अड्कल जे जस्ता भए तापनि बझाङ जिल्लाको ढँडार नै मष्टोको उत्पत्ति भएको सर्वाधिक प्राचीन स्थल हो भन्ने कुरामा अधिकांश मानिसहरूको सहमति छ। ढँडार मष्टोको एउटा मूल धामी हुन्छ। त्यो ढँडार मष्टोका धामीको मृत्यु भएपछि मात्र अर्को धामी हुने र भित्र पूजा गर्ने अर्को धामी बन्ने गर्दछन्। बाहिर बत्ती बाल्ने र अन्य काम गर्ने अन्य हुन्छन्। ढँडार मष्टोका हालसम्म ज्ञात पुजारीहरूमा परिङ्ग्या परिवारबाट १२ पुस्ता, सुवासकोटी नयरका १० पुस्ता, सुवेदी परिवारका १२ पुस्ता र जैसी परिवारका कुशु जैसीबाट सुरु भएर हाल १८औँ पुस्ताले मूल पुजारीको रूपमा काम गरिरहेका छन्। यसबाट यो मन्दिरमा मष्टो पूजाको परम्पराको प्राचीनताको अनुमान गर्न सकिन्छ। किंवदन्ती अनुसार मष्टो ढँडारमा जाँदा ढँडारका मानिसहरू खर्कमा गोठालो गएका थिए। गोठमा गाई-भैँसीका दूध राखेका भाँडाहरू खर्कबाट गोठमा आउँदा रित्तो हुने क्रम दिनदिनै हुन थालेपछि दिउँसो सबै मानिसहरू खर्क गएको बेला कसले दूध चोरेर खान्छ पत्ता लगाउनुपर्यो भन्ने हिसाबले लुकेर चियो गर्दा एउटा स्याल जस्तो जीव आएर दूध चोरेर खान लागेपछि सो जीवलाई देखेर कराउँदा उक्त जीव त्यही गोठमा आगो बालेको ठाउँबाट जमिन घस्रिएर करिब ४ किलोमिटर टाढाको पैंयादरो भन्ने ठाउँमा निस्कियो, त्यसलाई पैंयादरोको मष्टो भनिन्छ। उक्त जमिन घस्रिएर बनेको प्वाल अहिले पनि यथावत नै छ। अर्को यसै सँग मिल्दोजुल्दो किंवदन्ती पनि प्रचलित छ। कुश भट्ट नामक एकजना मानिस तीर्थाटन गर्न विभिन्न तीर्थमा जाँदा शंखधारमा एउटा शिला भेटेपछि उक्त शिलालाई आफूसँग लिएर हिँडे। राती सपनामा शिलाले आफू बेबिलोनिया तिरको देवता भएको र साइपाल हिमालको प्रस्रवण क्षेत्रमा बस्न चाहेको बताएछ। त्यसपछि उनले ढँडारमा माडौँ (थान) बनाएर शिला स्थापना गरे। त्यस ठाउँमा बँदेलले गोठालाको दही चोरेर खाने गरेपछि गोठालाले बँदेल समात्न खोज्दा सबै गोठाला बेहोस भएछन् र के भयो भनेर हेर्न आउने मान्छेहरू मध्ये जसराज भन्ने गोठालालाई कम्प छुटेछ र "म मरुत हुँ तिमी खसको कुलमुली हुँ। दैत्यको प्रहारबाट भवानीलाई बचाउन आएको हुँ, मेरो मन्दिर बनाउनुको सट्टा साधारण माडौँ बनाई त्यसको गाभिरमा खोपो राख्नु र मेरो गााधी सम्झेर पूज्नु, मेरो बहिनीको पनि सम्झना गर्नु" भन्ने किंवदन्ती प्रचलित छ। अर्को भनाइ अनुसार बझाङको चैनपुर नजिकैको सुवेडाका जोशी ब्राह्मण शंखधार र जालन्धरबाट ढुङ्गा (शिला) को रूपमा आएको बान्नी गएपछि ती ब्राह्मणले झोली बिसाएपछि भगवान् लुप्त भए, त्यो ठाउँ देउबाँझ (बाँझको रूख) को टोड्का (ढँड वा कसै-कसैले ढँडार पनि भन्दछन्) त्यही ढँडमा मष्टोको जन्म भयो। त्यहाँ बाँधिएकाले 'बान्नी मष्टो' भनियो। त्यहाँबाट विभिन्न ठाउँमा फैलिएकाले त्यसका भेदहरू भए। डोलने (हिँड्ने डुल्ने) भएकाले मष्टो-मष्टो भन्न थाले। १२ अङ्गालको मष्टो भन्ने पनि गरिन्छ, यसको मतलब मष्टोका १२ भेद भनेको होला। १२ ठाउँमा बसेकाले १२ उपमष्टो भनेको हो। मूल रूपमा मष्टोका दुई भेद छन्। मष्टो एउटै भए तापनि मष्टोले कहिले दूध र कहिले बलि खाने भएकाले एउटै मष्टोलाई दुधे मष्टो र दाह्रे मष्टो भनिएको हो। मूल थलोबाट मानिस अन्यत्र सरेर जाँदा र मष्टोका अनुयायीहरू विभिन्न ठाउँमा बढ्दै जाँदा विभिन्न ठाउँमा मष्टोका माडौँ स्थापना हुँदै त्यहीँका ठाउँ अनुसार मष्टोका भेदहरू बढ्दै १२ मष्टो, १८ मष्टो हुँदै मष्टोका १०० भन्दा बढी भेदहरू उल्लेख भएको पाइन्छ। जस्तै: बझाङको छबिस पाथीभेरा गाउँपालिकाको बान्नी भन्ने गाउँमा आएर बसे बान्नी मष्टो, मुगुको कावा मष्टो, बिजुली डाँडामा बसेको बिजुली मष्टो, ढँडारमा बसेको ढँडार मष्टो, थापा गाउँमा आएको थापा मष्टो। मानिसको बसाइँसराइ जहाँ-जहाँ भयो त्यहीँ मष्टो थान स्थापना गर्दै गए, कालान्तरमा जुन-जुन ठाउँमा मष्टो थान स्थापना भए त्यही ठाउँको नामबाट मष्टो नामाकरण हुँदै गए। यसरी एक सयभन्दा बढी ठाउँमा स्थापित मष्टोलाई त्यसका प्रकारको रूपमा भ्रमपूर्ण व्याख्या गरियो। दाह्रे मष्टो र दुधे मष्टो यसका केही उदाहरण निम्न छन्: १. कावा मष्टो २. कालो सिल्लो मष्टो ३. कफल्ना मष्टो ४. कैलाश मष्टो ५. कुड्या मष्टो ६. कालिकोट मष्टो ७. कालो मष्टो ८. कैली मष्टो ९. कुलदेव मष्टो १०. कालढुङ्गी मष्टो ११. कलसैन मष्टो १२. कमल मष्टो १३. कुँवरडा मष्टो १४. काफल मष्टो १५. कुर्मी मष्टो १६. कुमारी मष्टो १७. काँडा मष्टो १८. गदशितल मष्टो १९. चुनभ्यो मष्टो २०. चण्डक मष्टो (पिथौरागढ) २१. छल मष्टो २२. छन्ना मष्टो २३. जगन्नाथ मष्टो २४. टेडी मष्टो २५. तुसापानी मष्टो २६. ठिङ्गाल मष्टो २७. डडुवा मष्टो २८. दधिसिलट मष्टो २९. ढँडार मष्टो (आदिमष्टो) ३०. धाड्या मष्टो ३१. धुडीधुस्के मष्टो ३२. धोर मष्टो ३३. तेडी मष्टो ३४. तालिकोट्या मष्टो ३५. तमाचारी मष्टो ३६. थापा मष्टो ३७. दाह्रे मष्टो ३८. दुध्या (दुधे) मष्टो ३९. दुधेशिल्टो मष्टो ४०. दयाशिला मष्टो ४१. दुधेवराह मष्टो ४२. दाने मष्टो ४३. धुरङ्गो मष्टो ४४. धुपीरूख्खा मष्टो ४५. धौलीपुर्या मष्टो ४६. धौलापानी मष्टो ४७. धुसापानी मष्टो ४८. निगुनीको मष्टो ४९. पैंक मष्टो ५०. पन्त्या मष्टो ५१. पुआल्या मष्टो ५२. पञ्चालो मष्टो ५३. बुढ मष्टो ५४. विनायक मष्टो ५५. बिजुली डाँडा मष्टो ५६. बाबिरो मष्टो ५७. बबु मष्टो ५८. बाटपाल मष्टो ५९. बगारे मष्टो ६०. बडाकोटी ६१. बाजकोट्या मष्टो ६२. बाँसकोट्या मष्टो ६३. भ्वीन मष्टो ६४. भुवार मष्टो ६५. भैरो (भैख) मष्टो ६६. भुइँफुट्टो मष्टो ६७. भात्याखोला मष्टो ६८. भागे मष्टो ६९. भूमिराज (दार्चुला/बैतडी) मष्टो ७०. महावै मष्टो ७१. महादेउ मष्टो ७२. मशालो मष्टो ७३. मण्डली मष्टो ७४. मुण्डा मष्टो ७५. महारुद्र धौता मष्टो ७६. माटो मष्टो ७७. महामष्टो ७८. मामादेव (राजस्थान भारत) ७९. मामाजी (भारत) ८०. रुमाल मष्टो ८१. राउतकोट्या ८२. रामपाल मष्टो ८३. रागमचुला मष्टो ८४. राहदेउ मष्टो ८५. रुद्र मष्टो ८६. रुपा मष्टो ८७. लिगुनी मष्टो ८८. लताशिल्टो मष्टो ८९. लाकुडो मष्टो ९०. लखुरो मष्टो ९१. लडिपाल मष्टो ९२. लोहासुर मष्टो ९३. लामा-विष्णु मष्टो ९४. लड्या मष्टो ९५. लाटो धौ ९६. लाटोबाहुन मष्टो ९७. लहुरेवरा मष्टो ९८. लिउडी मष्टो ९९. लेखालि-डी मष्टो १००. वातिपाल मष्टो १०१. बान्नी मष्टो १०२. वाईफाला मष्टो १०३. वडावडा मष्टो १०४. शम्भु मष्टो १०५. साहिलाकम्ब मष्टो १०६. साइबारा मष्टो १०७. श्वेता मष्टो १०८. साइन मष्टो १०९. सुपारी पण्डित मष्टो ११०. सड्या मष्टो १११. सीम मष्टो ११२. सुनारगाउँ मष्टो ११३. सिमताडी मष्टो ११४. सुम्लेगुरो मष्टो ११५. सिद्ध मष्टो ११६. साकिदेउ मष्टो ११७. सर्किदेउ मष्टो ११८. हगुरो मष्टो ११९. हयाङ्ग्र मष्टो १२०. हिङ्गाल मष्टो १२१. ह्युना मष्टो १२२. क्षेत्रपाल मष्टो १२३. अछामी मष्टो १२४. आद्य मष्टो १२५. उखाडी (गुलाडी) मष्टो १२६. उब्या मष्टो १२७. खापर मष्टो १२८. खप्पा मष्टो १२९. खैरे मष्टो १३०. गुरो (गुरौ) मष्टो १३१. गुच्चु मष्टो १३२. गन्या मष्टो १३३. विजय मष्टो। मष्टोहरूको स्वभाव वा प्रकृति हेरेर यिनीहरूलाई गुणको आधारमा सत्त्व, रज र तम गुण युक्त हुने भनिन्छ। सत्त्वगुण भएका मष्टोहरूमा दुधे मष्टो, मण्डली मष्टो, लडे मष्टो आदि पर्दछन्। रजोगुण वा राजसी गुण भएका मष्टोहरूमा दाह्रे मष्टो, रुमाल मष्टो, तेडी मष्टो, खापर पर्दछन्। तमोगुण भएका मष्टोमा कालो मष्टो, रुपा मष्टो, कैलो मष्टो, मुण्ड मष्टो आदि पर्दछन्। ढँडार स्थित दाह्रे मष्टो ज्येष्ठ र श्रेष्ठ मानिन्छन्। थापा मष्टो विद्वान् मष्टो, बाबिरो मष्टोलाई कान्छो मष्टो मानिन्छ। गुरौ मष्टो र विजय मष्टोलाई भाइराजा मष्टो भनिन्छ। मष्टो उपासना गर्दा वैदिक विधि नअपनाएर धामीले प्राकृतिक विधि अपनाएर काँप्दै पूजा गर्ने गर्दछन्। मष्टो देवताको मूर्ति हुँदैन, यसमा स्वर्ग-नर्कको परिकल्पना गरिएको पाइँदैन। मष्टोको पूजा गर्दा साह्रो-गाह्रो पर्दा पनि भाकल गरी पूजा गर्ने पनि गरिन्छ। ढँडारमा मष्टो पूजा गर्दा विभिन्न जातजातिहरूको सहभागिता हुन्छ। दाह्रे मष्टोले मष्टो थानमा बलिको लागि लिएको बोका दाँतले छिनाल्ने गरिन्छ। बलि दिने सम्बन्धमा एउटा रोचक किंवदन्ती प्रचलित छ। एकपल्ट बझाङी राजाले बलि दिनुपर्यो भन्दा माघको महिनामा बलि दिन मिल्दैन भनेपछि राजाले नमानी बलि दिन हठ गरेछन्। त्यसपछि राजाले निकै जिद्दी गरेपछि मष्टो चलेछ र राजाले बोकालाई गाईको बाच्छो बनाइदिएछन्। मष्टोले त्यो देखेर त्यसलाई बाघ बनाइदिए, मष्टोले बाघ बनाएको देखेर राजाले सर्प बनाइदियो। राजाले सर्प बनाएपछि मष्टोले गरुड बनाइदिए। राजाले बोकाको घाँटीमा फलामको पाता बाँधिदियो र मष्टोले पातासहित बोकाको घाँटी दाँतले छिनालिदिए। त्यो देखेर राजा रिसायो। अहिले पनि मष्टो चल्यो भने मष्टोले "तँ जिउँदो होइज म पन्छी होइजुँ, तँ खैर होइज म बाघ होइजुँ" भनी बोल्दछन्। ढँडारमा शनिबार र मंगलबार बलि (दाँतले) दिइन्छ। अरू बार दूध, चामलले पूजा गरिन्छ। पर्वको समयमा चैते दशैँमा बलि हुन्छ। जन्माष्टमीमा बलि हुँदैन। जुठो, सुतक परेको बेला मष्टोको पूजा हुँदैन। ढँडारमा नयाँ धामी निस्किए भने देउता चढेपछि दाँतले बोका छिनाल्नुपर्ने र धामी प्रमाणित भएपछि मष्टो देवताको अवतार भयो भनी ताल्कोटी राजाले धरी, पगडी, कानमा मुन्द्रा, बाला प्रदान गर्दछन्। त्यसपछि कुँवर जाति अनि ब्राह्मण जाति हुँदै अन्य हिलो पूजामा सहभागी हुन्छन्। मष्टो धामीमा मात्र आउँदछ। जुनसुकै नयाँ बाली भए पनि दाह्रे मष्टोलाई चढाएर मात्र आफूले खाने चलन छ। धामीले जाँड-रक्सी खानु हुँदैन। बलि दिने बेलामा धामीको स्वरूप डरलाग्दो हुन्थ्यो। त्यस्तो डरलाग्दो स्वरूप देखेर मानिसहरू डराउने भएकाले कपडाले छेकेर बलि दिने गरिन्थ्यो। जति बोका बलिका लागि ल्याइन्थ्यो ती सबैलाई दाँतले छिनालेर बलि दिने गरिन्थ्यो। बझाङी राजा गजराजले धामीको जाँच गर्न बोकाको घाँटीमा फलामको पाता बाँधेर बलि दिन ल्याएको र सो बोकालाई पातासहित दाँतले छिनालेको भनाइ छ। मष्टो भनेको एउटा मात्र हुन्छ। दाह्रे मष्टो र दुधे मष्टो भनेको एउटै मष्टोका राजसी र कार्यकारी वा रज र सत्त्व स्वरूप हो भन्ने मत पनि छ। दाह्रे र दुधे मष्टो भनेको एउटै हो मष्टोको संयुक्त रूप हो। आइतबार र बुधबार दुधे मष्टोको पूजा गरिन्छ दाह्रे मष्टो पनि सँगै हुन्छ। जुम्लाका मानिसहरू प्रायः ढँडारमा पूजा गरेपछि त्यहाँबाट बक्साएर अन्यत्र जान्छन्। ढँडार नै मष्टोको मूल थलो भएको र यसरी विभिन्न ठाउँमा विभिन्न नामका मष्टोहरू मूल स्थानबाट छुट्टिएर जुन-जुन स्थानमा गएर बसे त्यसै ठाउँको नामबाट ती ती मष्टोको नामबाट चिनिन थाले। खस जातिको पुरापूर्वकालमा १२ वटा समूह रहेको र हरेक समूहले छुट्टाछुट्टै मष्टो पूजा उपासना गर्ने भएकाले 'बाह्र भाइ मष्टो' भनिएको धेरैको अनुमान छ। बाह्र भाइ मष्टो को हुन् भन्ने बारेमा मतैक्यता छैन। कहीँ-कहीँ मष्टोलाई शिवको अंश मानेर पूजा गर्ने चलन पनि छ। कतिपयले मष्टोलाई इन्द्रपुत्र भन्ने विश्वास गर्दछन्। मष्टोका ५२ वीर र १६ मर्सानीहरू सुरक्षार्थ रहन्छन् भन्ने मान्यता पनि पाइन्छ। मष्टो सम्बन्धी विभिन्न किंवदन्तीहरू प्रचलित छन्। एउटा किंवदन्ती अनुसार एकपटक मन्दिरको नजिकै बसेर वेदपाठ गरिरहेका धवलपुरलाई असुरले टुक्रा-टुक्रा बनाएर मार्ने र उनले पढिरहेको वेदलाई जलाउने योजना बनाए। असुरको यो योजना थाहा पाएपछि मष्टोको भान्जा बान्नी मष्टोले वेदलाई मष्टोमाण्डौ नजिकै शिलामा परिणत गरिदिए र असुरको हातबाट मामा धवलपुरको ज्यान बचाए। त्यसै बेलादेखि मष्टो उपासकले भान्जालाई झोलीको देवता मान्ने गरेका हुन्। झोलीको देवतालाई मष्टोसँगै शिला स्थापना गरेर भान्जाको पनि पूजा गर्ने परम्परा चलेको हो भन्ने गरिन्छ। मष्टो सम्बन्धी एउटा आख्यान अनुसार देवासुर संग्राममा असुरहरूले पराजय भोगेपछि देवताहरूसँग शरण माग्न बाध्य भए तापनि उनीहरूको मनमा द्वेष बाँकी थियो। पछि असुर संगठित भए र उपद्रो गर्न थाले। आफूलाई पतन गराउने कारकको रूपमा दुर्गा भवानीलाई मानेर उनको अपहरण गरे। केहीले उनीमाथि बलात्कारको प्रयास समेत गरे। देवताहरूले अनेकौँ प्रयत्न गर्दा पनि देवी दुर्गालाई बन्दी बनाएको ठाउँ पत्ता लगाउन नसकेर भगवान् शंकरको आराधना गरे। त्यसपछि शंकरका शक्तिशाली गण देवता मष्टोको नेतृत्वमा युद्ध दलले दुर्गा र उनका बहिनीहरूलाई मुक्त गरी असुरहरूलाई छिन्नभिन्न पारेका हुनाले नवदुर्गाले मष्टोलाई भाइ भनी मानेकाले दुर्गा पूजा हुँदा मष्टोको आह्वान गरिनुका साथै मष्टोले देवभाग पाउने भए। मष्टोलाई दुष्टको दमन गर्ने, खराब विचारले अभिप्रेरित स्वार्थी र दुष्टात्मालाई दमन गर्ने र निमुखा र सत्यको पक्षमा कल्याणकारी देवताको रूपमा खसहरूको रक्षा गर्ने महान् देवताको रूपमा आदिकालदेखि पूजा, भक्ति र श्रद्धा गर्ने देवताको रूपमा खसहरूले पुज्दै आएका छन्। उपेक्षित, अपमानित, दुःखी मानिसहरूलाई बढ्ता स्नेह गर्ने भएकाले मष्टो समस्त खसहरूको लोकप्रिय देवता हुन पुगेका छन्। अर्को किंवदन्ती अनुसार सान्नी राज्यका राजा जसलाई सन्याल राजा पनि भनिन्छ। बाइसे राज्य कालको समयमा हालको कालिकोट जिल्लाको मेहेलमुडी गा.वि.स. मा सान्नी राज्यको राजधानी थियो। उनको राज्यमा सान खड्का र संसारे खड्का नाम गरेका २ भाइ थिए। ती दुई भाइमध्ये सानलाई दाह्रे मष्टो चढ्यो। दाह्रे मष्टो चढेपछि सीधासाधा सानले अस्वाभाविक कार्य गरेको देखेर सन्याल राजाले देउता चढ्यो कि दानव चढ्यो भनेर जाँच गर्ने विचार गर्दा राजा र देवता बीच लडाइँ भयो। राजाका दुई भाइ भान्जा र कुवेर थिए। भान्जाले केही नगरे पनि कुवेरले धनुकाँडले धामीलाई लखेट्न थाल्यो। दाह्रे मष्टो चढेका धामी त्यहाँबाट भागेर एउटा ठुलो रूखमा चढे र त्यहाँ पनि उसलाई लखेट्दै राजा आएकाले नजिकैको चुरी खोलामा फाल हालेर वेपत्ता भए। राजा पनि धामी मरे भन्ने ठानेर घर फर्कियो। धामी मरेको हल्ला फैलिएपछि उनकी पत्नी सती जाने तयारी गरिरहेको बेला धामी सर्पको कडेली (लगाम) बाघको घोडा चढेर दाह्रे मष्टो चढेका धामी आए। राजाले त्यो कुरा थाहा पाएर उनलाई मार्नको लागि ४०० भेडा राखेको खोरमा थुनेर सबै झ्याल ढोका बन्द गरिदिए। मष्टो चढेका धामीले ४०० भेडा मध्ये एउटा खसी बाहेक सबैलाई दाँतले छिनालेर मारे। त्यो देखेर भेडी गोठालो अत्यन्त दुःखी भयो। मष्टोले उसलाई सान्त्वना दिँदै उसलाई धनधान्यले पूर्ण गरी उसको सन्तान कहिल्यै नमासिने र कहिल्यै वृद्धि पनि नहुने वरदान दिए। उनका कयौँ पुस्ता बितिसक्दा पनि अहिलेसम्म उनका सन्तानहरूमा एकजना मात्र जन्मने कुराको निरन्तरता अहिलेसम्म पनि पाइन्छ। सन्याल राजाले मष्टोमाथि गरेको दुर्व्यवहारले उनीहरूका घरमा सधैँ कलह अशान्ति र हैरानी भइरहने भएकाले त्यहाँबाट अन्यत्र सर्ने विचारले जाने बेला लाकुर देवतासँग बिदा हुन गए। लाकुर देवता मष्टोका भान्जाले सम्झाए र दाह्रे मष्टोको सेवा गर्ने सल्लाह दिए। सन्याल राजाले दाह्रे मष्टोको मन्दिर निर्माण गरे। आफ्नो सम्पूर्ण सम्पत्ति, राज्य दाह्रे मष्टोलाई चढाउने प्रस्ताव गरे। दाह्रे मष्टो चढेका धामीहरूसँग यस्तो प्रस्ताव राखेपछि मष्टोले "सबै राज्य सम्पत्ति चढाएपछि तँ कहाँको राजा हुन्छस्? मलाई सबै सम्पत्ति चाहिँदैन, ३ भाग लगाएर २ भाग तिम्रा भाइले बाँड्नु, १ भाग मलाई दिनु" भनेको र राजाले सोही अनुसार गरेकाले दाह्रे मष्टोले सन्यालको एक अंश खाएकाले सन्याललाई भाइपीठ्या भनेर मष्टो चढेको बेला भन्ने गरिन्छ। डा. जगमान गुरुङले जुम्ला सिंजा पाण्डुसेरामा प्रचलित १२ मष्टोका नाम उल्लेख गरेका छन्। १. आदिमष्टो २. कालो मष्टो ३. बबुरो मष्टो ४. रुमाल मष्टो ५. दुधे मष्टो ६. दाह्रे मष्टो ७. मण्डली मष्टो ८. बान्नी मष्टो ९. थापा मष्टो १०. ढँडार मष्टो ११. कावा मष्टो १२. खापर मष्टो। हुम्लाको सोरुदरामा रहेको गुरौ मष्टोलाई कसै-कसैले देवताको रूपमा मान्दैनन्। यो अत्यन्त दुष्ट स्वभावको राक्षसी व्यवहार देखाउने खालको हुने बताइएको छ। मष्टो कुन देवता हुन् भन्ने बारेमा फरक-फरक मत पाइन्छ। कसैले वायुको रूपमा, कुनै अवस्थामा साधुको रूपमा, कुनै-कुनै अवस्थामा गरुडको रूपमा र कहीँ-कहीँ बिरालोको रूपमा मष्टो रूपान्तरित हुन्छन् भन्ने मत पाइन्छ। मष्टोलाई कुल देवता र इष्ट देवताको रूपमा पनि लिने गरिन्छ। कतिपय मानिसहरूले वराह मष्टो भन्ने गरेपछि जुम्लाका १२ भाइ मष्टोको अपभ्रंश रूप र जुम्लाको कालिकोट दरामा ढँडार मष्टोलाई पाण्डवको अवतार, खापर मष्टोलाई इन्द्रको छोरा भन्ने कुरा बाहुन र ठकुरीले हालेको कथामा मात्र पाइन्छ भन्ने कुरा डा. जगमान गुरुङले मान्दछन्। प्युठानमा बसोबास गर्ने खप्तडी बस्नेतहरू कैलासिनी, विन्ध्यवासिनी आदि नौ बहिनीको दिवाली पूजा गर्ने गर्दछन्। कौशिक गोत्रीय बस्नेतहरूका कुलदेवता कसरी फरक-फरक? कौशिक गोत्रीय खप्तडी बस्नेतहरूका कुल देवता दाह्रे मष्टो हुन्। पश्चिम नेपालका सबै बस्नेतहरू दाह्रे मष्टोलाई कुल देवताको रूपमा मान्दछन्। पूर्वतिरबाट बसाइँ सरेर आएका बस्नेतहरू बाहेक सम्पूर्ण बस्नेत लगायत अरू धेरै थरहरूका कुल देवता पनि दाह्रे मष्टो नै हुन्। तर पूर्व नेपालका विभिन्न ठाउँमा बस्ने कौशिक गोत्रीय खप्तडी बस्नेतहरू खापर मष्टोलाई आफ्नो कुल देवता मान्दछन्। प्युठानमा बसोबास गर्ने खप्तडी बस्नेतहरू कैलासिनी, विन्ध्यवासिनी आदि नौ बहिनीको दिवाली पूजा गर्ने गर्दछन्। एउटै थर गोत्रका मानिसहरू बीच कुल देवता किन फरक भन्ने प्रश्न उब्जनु स्वाभाविकै हो। यो कसरी यस्तो हुन गयो, त्यस बारेमा सोधखोज र निरुपण नहुञ्जेल अलग कुल देवता मान्ने बस्नेतहरू बीच कुल देवताको बारेमा केही भ्रमहरू रहिरहने भएकाले तथ्य के हो भन्ने बारेमा उजागर गर्न आवश्यक छ। प्राचीन कालमा बाह्र भाइ मष्टोहरू ढँडारमा बसेको बेला उनीहरू बीचमा वैमनस्यता उत्पन्न भएर ठुलो द्वन्द्वको स्थिति आयो। भरसक सबैलाई मिलाएर लैजाने जेठो र सर्वाधिक शक्तिशाली दाह्रे मष्टो (जसलाई गादी मष्टो पनि भन्दछन्), उनी सबैका नायक गद्दीमा राज गर्ने भएकाले र सबैका अगुवा नायक भएकाले द्वन्द्व हुन नदिन निरन्तर प्रयत्नशील हुन्थे। निरन्तरको मनमुटाव र द्वन्द्वको स्थिति कायमै रहेको बेला एक दिन सबै भाइ खप्तडको जङ्गलमा मालिङ्गो काट्न जाने सल्लाह भयो। त्यहाँ खानको लागि रुमालमा बाबर (रोटी), ठेकीमा दही, दूध, मालिङ्गो काट्ने हतियार समेत लिएर उनीहरू गए। मालिङ्गो काटिरहेको बेला अकस्मात उनीहरूमा झगडा पर्न गयो। सबैलाई सम्झाई-बुझाई गरी शान्त गर्न जेठो दाह्रे मष्टोले अनेक प्रयत्न गर्दा पनि अरू भाइले नमानेको र लडाइँले झन्-झन् उग्र रूप लिएकाले दाह्रे मष्टो रिसाएर दाह्रा किट्दै भर्खरै काटेको मालिङ्गोको ठुटाले हानेर एकजनाको खप्पर फुटाइदिए। त्यसरी खप्पर फुटाई माग्ने खापर/खापर मष्टो भनियो। अर्कोलाई कालो शिलाले हिर्काएर भगाएको, उनी उक्त शिला टिपेर भागे र अछामको विनायककोठ गए र विनायककोठे राजासँग द्वन्द्व भएपछि त्यहाँबाट भागेर विनायक भन्ने स्थानमा गएर आफूसँग भाग्दा लिएको कालो शिला त्यहीँ स्थापना गरे र कालो सिल्लो मष्टोको रूपमा स्थापित भयो। रोटी बोकेर ल्याएको रुमाल टिपेर भाग्ने खिड्कीसैनीमा गएर बस्यो र रुमाल मष्टोको नामले स्थापित भयो। अर्को भाइले सँगै ल्याएका बाबर टिपेर त्यहाँबाट भागेर जुम्लाको बाबिरो गाउँमा गएर बसेकाले बाबिरो मष्टोको रूपमा चिनियो। दूध-दही बोक्ने अलि सोझो अरूसँग झगडा नगर्ने सोझो भाइलाई आफूसँगै बस्न आग्रह गरेको र आफू पछिको स्थान ग्रहण गर्न सक्ने छुट दिएकाले उनी दुधे मष्टो कहलाएर उनलाई आफू पछि दूधको धार दिने व्यवस्था मिलाए। सबै भाइको आ-आफ्नो स्थान पाएकाले उनलाई ढल्लुको भाग दिए र त्यहाँ उनको धाम स्थापित गरे। उता खप्पर फुटाई मागेको खप्पर/खापर मष्टो त्यहाँबाट भागेर डोटी क्षेत्रतिर गए। त्यस समयमा डोटी, बोगटान, दार्चुला, कत्युरी राजवंशको अधीनमा थियो। कत्युरी राजवंशको स्थापना सातौँ शताब्दी आसपासमा सम्राट बासुदेवले गरेका थिए। यो राज्यको पहिलो राजधानी जोशी मठ र दोस्रो राजधानी बैजनाथ रणचुलाकोट थियो। यिनीहरू भगवान् केदारनाथ (शिव) भगवान्का भक्त थिए। यिनीहरू स्वामी कार्तिकेयको पूजा गर्दथे र कार्तिकेयबाट कार्तिकेयपुर र कार्तिकेयपुरका शासक भएकाले उनीहरूको वंशलाई कत्युरी वंश भनिएको मान्ने गरिन्छ। वैशाख शुक्ल मोहनी एकादशीको दिन कार्तिकेयलाई कार्तिकेयपुरबाट डोटीमा ल्याएपछि मोहनी एकादशीबाट उनलाई मोहण्याल नामले ख्याति प्राप्त भयो। यिनै मोहण्याल कत्युरीहरूका कुल देवता हुन्। कार्तिकेयको जन्मेको बारेमा पनि रोचक किंवदन्ती छ। भगवान् केदारनाथ (शिव) का दुई पुत्रहरूको जन्म भयो, गणेश र कार्तिकेय। दुई पुत्रको जन्म भएपछि केदारनाथ अत्यन्त खुसी भए र उनले आफ्ना दुई पुत्रको बारेमा जान्न जोशीमठका ज्योतिषीलाई देखाउँदा ज्योतिषीले गणेश महान् विद्वान्, बुद्धिमान् हुने र कार्तिकेय महान् बलशाली हुने, ती कार्तिकेय मूल नक्षत्रमा जन्मेको र केदारनाथलाई अनिष्ट हुने कुरा बताएपछि मोहनीलाललाई केदारनाथले तामाको ढोलभित्र हाली मन्दाकिनी नदीमा बगाइदिए। यो नदी हिमालयको चोरबारी दहबाट उत्पन्न भएर सोन प्रयागमा कालीगङ्गासँग र बद्रीनाथबाट आउने अलकनन्दा नदीसँग रुद्र प्रयागमा मिल्दछ। नदीमा अलि तल गोविन्दघाट नामक स्थानमा माझीले जाल हानिरहेको बेला अयोध्याका राजा घोडामा सवार भएर त्यहाँ पुगे। मन्दाकिनी नदीमा मोहण्याललाई हालेर बगाएको तामाको ढोल बग्दै त्यहाँ आएको देखेर त्यो के चिज हो भन्ने कौतूहलता लागेर राजाले माझीलाई जाल हान्न लगाएर त्यसलाई नदी किनारमा ल्याउन लगाए। माझीले त्यो ढोललाई जालमा पारेर नदी किनारमा ल्यायो। अलि पर नदी किनारमा लिएर राजाले त्यो ढोल खोलेर हेर्दा त्यसबाट बालक मोहण्याल निस्किए। उक्त ठाउँ त्यसै गोडियाको नामबाट गोविन्दघाटले प्रसिद्ध भयो। मोहण्याललाई विश्व भित्रका सन्ततिले उत्सवपूर्वक पूजाआजा गरे। त्यसबेला तामाको ढोल बजाउने कश्यप गोत्रीय ऐरी मोहण्यालको ढोली भयो। उता भागेर डोटी पुगेको खापरे/खापर मष्टोले मोहण्यालको माटो (राज्य) जहाँ "१२ बोघानका राजा मोहण्याल हुन्" भन्ने गरिन्छ, त्यहाँ गएर बलजफ्ती उनको पहाडी भू-भागमा कब्जा जमाएर आफ्नो हैकम जमाउन खोज्ने र त्यहाँका मानिसलाई दुःख दिएर आतंक मच्चाएको थियो। त्यस्तो स्थितिमा त्यही देवभूमिको देउताहरूले बडातोडो देउतालाई पुकारा गर्दै भने: "जान दैत्य बडातोडो मालथली जान। मोहण्याल दैत्यको दलु कत्युर लान..." देउताले यस्तो पुकार गरेकाले बडातोडो देउता मोहण्याललाई लिन मालथली हुँदै कत्युर गयो। "गयो दैत्य बडातोडो, बतासैको स्वर। आयो दलु मोहण्यालको बादलकी ढिक।" मोहण्यालको आगमन पछि मोहण्यालले आफ्नो गणलाई निर्देशन दिँदै भने: "मिल्ला छौ त खापरे, हामुसित मिल। नै त मिल्ला खापरेकी लाँत तेरी ठीक। केदारका दाहिने तिर तुड्या तुड्या पानी। नै त मिल्ला खापरेकी समाई ल्याए रानी। केदारैका गाथ मुनि थुम थुम केला। नै त मिल्ला खापरेका समाई ल्याए चेला।" त्यसपछि खापरसँग युद्ध हुन्छ। युद्धमा ५२ र ५३ दल भएका देवी देउताहरूले मोहण्याललाई सहयोग गरे। घमासान युद्ध भएपछि खापरको नराम्रोसँग हार भयो। खापरलाई नराम्रोसँग कुटी सेती नदी कटाएर लखेटे। युद्धमा मोहण्यालको खापरले दाँत भाँचिदिएको र मोहण्यालले खापरको बायाँ खुट्टा भाँचिदिएको थियो र आफ्नो भूमिमा उसले पूजा गर्न नपाउने गरिदिएकाले अहिले पनि खापर मष्टोका धामी एक खुट्टाले लङ्गडो भएर काँप्ने गर्दछन्। त्यसपछि खापरसँग युद्ध हुन्छ। युद्धमा ५२ र ५३ दल भएका देवी-देवताहरूले माहेन्याललाई सहयोग गरे। घमासान युद्ध भएपछि खापरको नराम्रोसँग हार भयो। खापरलाई नराम्रोसँग कुटी सेती नदी कटाएर लखेटे। युद्धमा माहेन्यालले खापरको दाँत भाँचिदिएको र माहेन्यालले खापरको बायाँ खुट्टा भाँचिदिएको थियो। आफ्नो भूमिमा उसले पूजा गर्न नपाउने गरिदिएकाले अहिले पनि खापर मष्टका धामीहरू खापर मष्टको पूजा गर्दा जमिनभन्दा अलि अग्लो अठारो (टाँड) बनाएर, त्यसलाई माहेन्यालले नदेखास् भनेर स्याउलाले बारेर खापरको पूजा गर्छन्। माहेन्यालले बायाँ खुट्टा भाँचेकाले खापरका धामीले काँप्दा बायाँ खुट्टा भाँचिएको आफ्नो देवताको नक्कल गरेर बायाँ खुट्टा उठाएर दायाँ खुट्टाले मात्र खोच्याउँदै काँप्ने र नाच्ने गर्छन्। अरू समयमा समेत घरको देवता राखेको कोठाको झ्यालमा माहेन्यालले नदेखास् भनेर स्याउला राख्ने चलन छ। खापर मष्ट पुज्ने खप्तडी बस्नेतहरूले आफूलाई प्रकृति पूजक हौं भन्ने गरे तापनि उनीहरूले खापर मष्टको बायाँ खुट्टा भाँचिएको मूर्तिको पूजा गर्ने गर्दछन्। यस्तो सयौं वर्षदेखि परम्परागत रूपमा पूजिँदै आएको घुँडाबाट बायाँ खुट्टा भाँचिएको, जनै लगाएको र कुर्सीजस्तो आसनमा बसेको खापर मष्टको धातुको प्राचीन मूर्ति कैलालीको मडकाैनाका बस्नेत परिवारमा सुरक्षित रूपमा पूजा स्थलमा रहेको र पूजिँदै आएको पाइन्छ। यस्तो मूर्ति राखिएको भँडारको झ्यालमा पूजा गर्दा माहेन्यालले नदेखुन् भनेर उनलाई छेक्नका लागि सधैं स्याउला राखिन्छ। खापर मष्टको पूजा गर्दा बोकाको बलि पनि भुईँमा दिन नमिल्ने भएकाले घरको माथि अठारोमा वा बाहिर पुज्दा जमिनमाथि बनाएको अग्लो टाँडमा दिने गरिन्छ। खापर मष्टको पूजा ३ वर्षमा १ पटक (वनदेवी कालिकासँगै राखेर) गर्ने गरिन्छ। यसरी माहेन्यालसँग नराम्रोसँग पराजित भएपछि आफ्नो बस्ने ठाउँ कतै नभएको र पश्चिम, उत्तर, दक्षिण र पूर्वतिर समेत माहेन्यालको राज्य भएकाले त्यहाँबाट खापर मष्ट र त्यसका अनुयायी तथा खापर मष्टका पूजक बस्नेतहरू देवतासहित भागेर पूर्वतिर लागे। युद्धमा धेरै धनजनको क्षति भएको र नजिकै बस्दा १२ बथानका राजा समेत रहेको माहेन्यालको सधैं भय रहिरहने भएकाले डोटी क्षेत्रबाट भागेर गएकाहरू र तिनका सन्तानहरू गण्डकी क्षेत्रको लमजुङ आसपासमा बसोबास गरे। पछि द्रव्य शाह लिगलिगकोटको दौडमा विजयी भएर राजा भएको समयमा द्रव्य शाहका नजिकका सहयोगीको रूपमा उनीहरू त्यहाँ रहे र पछि गोरखा दरबारका विश्वासपात्र बने। सहयोगीमध्येका भूपालमानका सन्तान गोरखा मै बसे र वंशराजका छोराका सन्तान पूर्वतिर हान्निए। तिनीहरू त्रिशूली पार गरेर नुवाकोट र नुवाकोटपछि दोलखातिर गए। त्यहाँका मानिसहरूसँग मिल्न नसकेपछि स्थानीय मानिसहरूले खप्तडी बस्नेतहरूलाई लखेटे। त्यहाँबाट भागेर वेताली गए। वेतालीका मानिसले पनि त्यहाँबाट लखेटेर लिखु खोलामा सुनुवारहरूको किपट भएको जमिनमा गए। पछि सुनुवारले त्यहाँबाट पनि धपाउन खोज्दा सुनुवारलाई चलनचल्तीको तिरो तिरेर बसे। केही समयपछि उनीहरूका सन्तानमध्ये एक भाइ सोलु र अर्को भाइ भोजपुरतिर गए। भोजपुरका शक्तिशाली राईले आफ्नी छोरीमाथि आँखा लगाएकाले राईबाट छोरी जोगाउन भागेर दूधकोशीको पश्चिम किनारातिर बसाईँ सरेको र यसरी गण्डकी क्षेत्रबाट पूर्वी नेपालका विभिन्न क्षेत्रमा खापर मष्टका अनुयायी बस्नेतहरू फैलिएर बसेको हुँदा उनीहरूसँगै खापर मष्ट उनीहरू बसोबास गरेको क्षेत्रतिर कुलदेवताको रूपमा मानिँदै आएको हो। पूर्वबाट बसाईँ सरेर पुनः पश्चिम तर्फ गएका अत्यन्तै नगण्य संख्याका बस्नेतहरूबाहेक पश्चिम तर्फ अनादिकालदेखि बस्दै आएका बस्नेतहरूले खापर मष्ट मान्ने गरेको पाइँदैन। १२ भाइ मष्टहरू धडाँर छोडेर विभिन्न ठाउँमा गएपछि दाह्रे मष्ट धडाँरमा भइरहे र उनका अनुयायी खप्तडी बस्नेतहरूको एउटा ठूलो समूह पनि त्यही रह्यो। लामो समयपछि जनसंख्या वृद्धि हुँदै जाँदा दाह्रे मष्टको एउटा पीठको रूपमा मुगुको खत्याड डाँडा कौवामा दाह्रे मष्टको माडौं स्थापना गरी कावा मष्टका रूपमा स्थापित भए। कौवाबाट कफल्लामा मष्ट सरेर आएको बताइन्छ। कफल्लामा मष्टको ख्याति चारैतिर फैलिएपछि ठूलो संख्यामा मानिसहरू आउने र ठूलो संख्यामा बलि चढ्ने गर्दा, बलि चलेको बेला धामीको श्रीमतीले दाह्रे मष्टप्रति नकारात्मक र दुर्वच्य बचन बोलेकाले त्यसको परिणाम स्वरूप उनको मृत्यु भयो। त्यसपछि दाह्रे मष्ट त्यहाँबाट बिजुली डाँडामा सरेर गएको र दार्नागाउँ र सिमपाखा गाउँलाई श्राप दिएको कारण अहिले पनि ती गाउँहरू उजाड भएर बस्ती हराएर गएको पाइन्छ। बिजुली डाँडामा केही समय बसेपछि त्यहाँबाट जाजरकोटको पैंकमा दाह्रे मष्ट सरेर गए। हाल बिजुली डाँडामा दुधे मष्ट मात्र रहेका र दाह्रे मष्ट पैंकमा सरेका छन्। यसरी विभिन्न कालखण्डमा विभिन्न स्थानमा मानिसहरूको बसाईँसराइसँगै उनीहरूले मान्ने कुलदेवता सँगसँगै जाने हुनाले दाह्रे मष्ट मान्ने कौशिक गोत्रीय खप्तडी बस्नेतहरू विभिन्न ठाउँमा बसाईँ सरेर गएको र त्यहाँ दाह्रे मष्टका मन्दिर स्थापित हुँदै गएको पाइन्छ। बझाङको धडाँरबाट दाह्रे मष्ट मान्ने कौशिक गोत्रीय खप्तडी बस्नेतहरू मुगु, जुम्ला, दैलेख, जाजरकोट, सल्यान, रुकुम, रोल्पा जस्ता पहाडी जिल्लातिर बसाईँसराइ गर्दै मष्ट माडौं स्थापित गर्दै गए। पछि तराईको राज्य एकीकरण र औलो उन्मूलनपछि सल्यान, रोल्पा, रुकुम, प्युठान आदि जिल्लाबाट दाङ; जुम्ला, कालिकोट, मुगु, दैलेख जस्ता पहाडी क्षेत्रबाट सुर्खेत, बाँके, बर्दिया र अछाम, डोटी, बझाङ, बाजुरा आदि स्थानबाट कैलाली कञ्चनपुर जस्ता तराईका जिल्लामा बसाईँसराइ गरेर आएका खप्तडी बस्नेतहरूले तत् तत् स्थानमा आफ्ना कुलदेवताको स्थापना गर्दै गए। यसरी विभिन्न ठाउँ जहाँ मष्टको स्थापना भयो, त्यसै ठाउँको नामबाट मष्टको नाम पनि रहन गयो। जस्तै: धडाँर गाउँबाट धडाँर मष्ट, बडु गाउँबाट बडु मष्ट, थार्प गाउँबाट थार्प मष्ट, बिजुली डाँडाबाट बिजुली मष्ट, कौवा गाउँबाट कावा मष्ट, पैंक गाउँबाट पैंक मष्ट आदि। १२ मष्ट जहाँ-जहाँ उत्पन्न भए, त्यहाँका मूल थलोहरूमा शिवलिङ्गहरू स्वतः उत्पन्न भएको मानिन्छ। यो कतै विभिन्न नामका शिलाको रूपमा र कतै शिवलिङ्गको स्वरूपमा प्रकट भए। मष्टलाई कतै शिवको सहयोगी र कतै शिवको अंशको रूपमा उल्लेख गरिएको छ। मष्टको माडौं तथा घरमा मष्ट स्थापना गरेको स्थानमा शिवलाई सिद्ध वा महादेवको रूपमा ध्वजा टाँग्ने गरिएको हुन्छ। सिद्ध (शिव) सात्त्विक देवता भएकाले बलि नचढाउने र उनलाई पानीको धार दिने गरिन्छ। त्यस्तै दाह्रे मष्टसँगै दुधे मष्टलाई पनि स्थापना गर्ने गरेको स्थिति भनेको मष्ट मूल रूपमा दाह्रे र दुधे मात्र हुन्छन्। दाह्रे र दुधे भनेको एउटै मष्टको दुई रूप सात्त्विक र राजसी भन्ने मान्यता पनि छ। त्यसैकारण दुधे मष्टलाई दूधको धार र दाह्रे मष्टलाई रक्त बलि दिने गरिन्छ। एउटै गुवारा (गुठी/पूजास्थल) भित्र ३ प्रकारका धार (पानी, दूध र रगत) चढाउने कार्य दार्शनिक हिसाबले मानिसले जीवन र जगत्को व्याख्या सृष्टि, स्थिति र संहारको सचेतनात्मक सांकेतिक अभिव्यक्तिको सूक्ष्म चेतनाको स्वरूपको अर्थमा लिन सकिन्छ। • जल (पानी): सृष्टिको प्रतीक हो। जीवनको प्रारम्भ वा सृष्टिको सांकेतिक अभिव्यक्ति हो। • दूध: स्थितिको प्रतीक हो। अर्थात् मानवीय कर्मको सांकेतिक अभिव्यक्ति हो। मानिस बाँच्नका लागि, पुरुषार्थका लागि र जीवनको सार्थकताका लागि कर्म गर्नुपर्दछ। कर्मबाट नै दूध, अन्न, फलफूल जस्ता कुराहरू प्राप्त हुन्छन्। • रगत (बलि): संहारको प्रतीक हो। संसारमा जन्मेपछि संहार वा अन्त्य अनिवार्य छ। यसबाट मुक्ति पाउन वा यसलाई छल्न सकिँदैन भन्ने कुराको सांकेतिक अभिव्यक्ति हो। यो माथि उल्लेखित उच्च तहको पूर्वीय दर्शनको उत्कृष्ट र समृद्ध अभिव्यक्ति पनि हो। यसले ईश्वरप्रतिको आस्था, कर्मप्रतिको आस्था र जीवनप्रतिको मोहबाट मुक्तिको प्रेरणा पनि दिन्छ। पूर्वीय दर्शनमा स्वर्ग, मर्त्य र पाताल लोकको गरिएको परिकल्पनाको सांकेतिक अभिव्यक्ति तर्फ पनि यसले संकेत गर्दछ। यसरी खप्तडी बस्नेतहरूले अपनाएको देवता र पूजा विधिहरू केवल धार्मिक आस्था र विश्वास मात्र नभएर जीवन, जगत्, कर्म आदिलाई बुझ्ने, बुझाउने र व्याख्या गर्ने अत्यन्तै उच्च तहको दार्शनिक चेतना पनि हो भन्न सकिन्छ। ________________________________________ सन्दर्भ सामग्रीहरू • (१) आचार्य, राजेन्द्र कुमार: पचहत्तर जिल्लाको लोककथा (संकलन र सम्पादन), २०७३, काठमाडौँ: ने.प्र.प्र. पृ. ११४-११५। • (२) खड्का, रामबहादुर: मष्ट संस्कृति र परम्परा। • (३) भट्टराई, विश्वनाथ: प्राचीन डोमेटी (डोटी) राज्यको राजनीतिक तथा सांस्कृतिक इतिहास (आलेख)। • (४) कार्की, तेज: के हो मष्ट संस्कृति? यस्तो छ यसको इतिहास (आलेख), golkhabar.com। • (५) मष्टो कुलदेवता प्रतिष्ठान: मष्टो इतिहास र संस्कृति। • (६) प्रज्ञा (पूर्णाङ्क ९७): वर्ष ४४, अङ्क २, २०६९ चैत। • (७) Regmi, D.R.: Medieval Nepal. • (८) Grierson, George Abraham: Linguistic Survey of India. • (९) Pokhrel, Balkrishna: Ancient Khas Culture. • (१०) Sharma, Balkrishna: The Origin of Khas System in Hinduism and its Relevance in the Present Context. • (११) Wikipedia: <nowiki>https://dty.wikipedia.org</nowiki> । [[विशेष:Contributions/&#126;2026-15382-66|&#126;2026-15382-66]] ([[प्रयोगकर्ता वार्ता:&#126;2026-15382-66|वार्तालाप]]) १५:४२, ११ मार्च २०२६ (नेपाली समय) == कौशिक गोत्र: इतिहास र परिचय राजेन्द्र बहादुर बस्नेत तुलसीपुर-६, दाङ == == कौशिक गोत्र: इतिहास र परिचय == '''राजेन्द्र बहादुर बस्नेत''' '''तुलसीपुर-६, दाङ''' कौशिक गोत्र के हो? यसको इतिहासको बारेमा धेरै मानिसहरूका लागि यो रहस्यको रूपमा रहेको पाइन्छ। आफूलाई कौशिक गोत्रका भन्नेहरूले पनि यसको बारेमा सामान्य जानकारी समेत राख्ने गरेको पाइँदैन। त्यसकारण सामान्य पाठकलाई जानकारी होस् भनेर यो सानो प्रयास गरिएको छ। भारतमा कौशिक वा उलूक एक सम्प्रदाय हो। प्राचीन भारतीय ग्रन्थहरूमा कुशिक नामका एक प्रख्यात मुनिको उल्लेख पाइन्छ, जो लकूलीशका शिष्य थिए। उनको नाममा उलूक सम्प्रदायको नाम कौशिक रह्यो। कुशिक नामका एक अर्का ऋषि पनि थिए, जो भगवान् विष्णुका भक्त र सामवेदी थिए। उनी ब्राह्मण थिए। उनको सामगान प्रसिद्ध थियो। उनको कथा तथा नारदको साम वा गायन सिक्ने कथा पनि प्रख्यात छ। कुशिक ऋषिका अनुयायी वा वंशजहरू पनि कौशिक भनिन्छन्। ब्रह्माका एक पुत्रको नाम कुश थियो, जो राजा पनि बने। यिनी कुशका वंशज पनि कौशिक भनिए। ब्रह्माका पुत्र भएका कारणले उनी कुश ब्राह्मण भए र उनका सन्तान कौशिक। कुशका चार पुत्र भए— कुशाम्ब, कुशनाभ, असुर्र्तजस र वसु। कौशिक गोत्रीय क्षत्रीय र ब्राह्मण दुवै पाइन्छन्, तर दुवैका पूर्वज विश्वामित्र थिए भन्ने कुरामा मतभेद पाइन्छ। ऋषि विश्वामित्रलाई पनि कौशिक भनिन्छ। विश्वामित्र क्षत्रीय थिए। गोत्र परम्परामा ब्राह्मणलाई छोडेर अन्य जातिहरूका मानिसको उनीहरूका गुरुहरूको नै गोत्र हुने गर्दछ, जस्तै: भगवान् रामको गोत्र उनका कुलगुरु वशिष्ठको नाममा रह्यो। अर्थात् भगवान् राम वशिष्ठ गोत्रका थिए। त्यस्तै प्रकारले विश्वामित्रको गोत्र पनि कौशिक भयो, किनभने ब्राह्मण कुलमा उत्पन्न भएका ऋषि कुशिक उनका गुरु थिए। यसैकारण ऋग्वेदमा उनलाई कौशिक भनिएको छ। उनलाई कौशिक भन्नुको अर्को कारण पनि छ। त्यस अनुसार विश्वामित्र ब्रह्माका एक पुत्र कुशका वंशज थिए, जसका कारण उनलाई कौशिक भनियो। केही ग्रन्थमा गाधिलाई कुशाम्बका पुत्र र अन्य केही ग्रन्थमा उनलाई कुशनाभका पुत्र बताइएको छ। यिनै गाधिका पुत्र विश्वामित्र थिए। विश्वामित्र जन्मले क्षत्रीय मान्दै आएको कारणले उनलाई ब्रह्माको पुत्र कुशका वंशज मान्न धेरै मानिस तयार छैनन्। किनभने यो कुरालाई मान्ने हो भने विश्वामित्रलाई ब्राह्मण मान्नुपर्ने हुन्छ, जो उनीहरू मान्न तयार छैनन् र यो विश्वामित्रलाई क्षत्रीय मानिरहेको परम्पराको विपरीत हुन जान्छ। हरिवंश पुराण र प्रायः अन्यत्र कतिपय ग्रन्थका अनुसार गाधि कुशाम्बका भाइ कुशिकका पुत्र थिए र इन्द्र स्वयम् गाधि बनेर अवतरित भएका थिए। यसबाट यो वंशको नाम कौशिक रह्यो। गाधिपुत्र विश्वामित्रलाई कौशिक भन्ने कारण यही थियो। हरिवंश पुराणको प्रथम पर्वको २७ औँ सर्गको श्लोक १२-१६ मा यसलाई स्पष्ट भाषामा उल्लेख छ। यसमा भनिएको छ कि कुशिकले इन्द्रको समान पुत्र पाउने इच्छाले तपस्या गर्न थाले, तब इन्द्र भयभीत भएर स्वयम् उनको पुत्र बनेर उत्पन्न भए। राजा कुशिकले एक हजार वर्ष तप गरेपछि मात्र इन्द्रको ध्यान कुशिकतिर गएको थियो। अति उग्र तप गरेर पुत्र पाउन उनी समर्थ देखेर सहस्राक्ष पुरन्दरले उनीमा आफ्नो अंश स्थापित गरे। यस प्रकार इन्द्र कुशिकका पुत्र बनेका थिए। (१३-१५) श्लोकमा भनिएको छ:<blockquote>''स गाधिरभवद् राजा मघवान् कौशिकः स्वयम्।'' ''पौरुः कुत्स्योऽभवद् भार्या गाधिस्तस्यामजायत।।''</blockquote>यदि विश्वामित्र जन्मजात क्षत्रीय थिएनन् भने सम्भव छ कुशाम्ब र कुशिक नामका अन्य कुनै व्यक्ति थिए होलान् जो क्षत्रीय थिए र ब्रह्माका पौत्र कुशाम्ब जो ब्राह्मण थिए, उनी अर्कै थिए। अनेकौँ ग्रन्थमा गाधिका पिताको नाम कुशनाभ तथा कुशनाभका पिताको नाम कुश तथा कुशका पिता ब्रह्माको उल्लेख पाइएको कारण भ्रम तथा विवादको स्थिति कायमै छ। यस प्रकार जो ब्राह्मण कौशिक गोत्रका हुन्, ती या ब्रह्माका पुत्र कुशका वंशज हुन् वा कुशिक ब्रह्मर्षिका सन्तान हुन्। कौशिक गोत्रीय ब्राह्मण कौशिक (विश्वामित्र) जो क्षत्रीय हुन्, उनका सन्तान हुन् भन्ने कुरा विश्वसनीय लाग्दैन। सम्भवतः कुशिक नामक ब्राह्मण विश्वामित्रका गुरु रहेका हुन सक्छन्, जसबाट विश्वामित्रको गोत्र कौशिक भएको होस्। तर कान्यकुब्ज तथा कतिपय ब्राह्मणहरू कौशिक गोत्रीय छन्। कतिपय विद्वान्‌ले उनीहरू कौशिकका सन्तान हुन् भन्ने कुरामा मतभेद राख्दछन्। जो कौशिक गोत्रीय क्षत्रीयहरू छन्, ती विश्वामित्रका वा क्षत्रीय राजा कुशिकका वा उनका पूर्वजका गुरु कुशिक ब्रह्मर्षिका सन्तान हुन्। अन्य कौशिक जातिहरूका पूर्वजका गुरु पनि सम्भवतः ब्रह्मर्षि कुशिक नै थिए। नेपालको कोशी नदीको किनारमा विश्वामित्रले तपस्या गरेर ऋषिको दर्जा प्राप्त भएको भन्ने उल्लेख छ। महाभारतमा पनि यो नदीको कौशिकी नामबाट उल्लेख गरेको पाइन्छ। कोशी नदीको किनारमा बस्ने भएको कारण त्यहाँका मानिसलाई कौशिक भनिएको भन्ने मत पनि पाइन्छ। प्राचीन उलूक वा कौशिक सम्प्रदाय तथा वैशेषिक शैव दर्शनसँग पनि कौशिकको सम्बन्ध पाइन्छ। कुनै कौशिकको सम्बन्ध कुशिक ब्रह्मर्षि र केहीको सम्बन्ध केवल सप्तकोशी नदीसँग रहन गयो। कौशिक 'उल्लू' वा लाटोकोसेरो नामक पक्षीलाई पनि भनिन्छ, तर यो पक्षी मूर्ख वा लाटो भने पटक्कै हुँदैन। === विश्वामित्र र कौशिक गोत्र === विश्वामित्र वैदिक कालका विख्यात ऋषि थिए। उनी महान् र तेजस्वी महापुरुष थिए। ऋषि धर्म ग्रहण गर्नुपूर्व उनी महान् प्रजावत्सल राजा थिए। उनले गायत्री मन्त्रको रचना गरेका थिए। '''क्षत्रीय राजाको रूपमा:''' प्रजापतिका पुत्र कुश (श्रीरामका पुत्र कुश होइनन्) का पुत्र कुशनाभका पुत्र राजा गाधि थिए। विश्वामित्र तिनै गाधिका पुत्र थिए। एकदिन राजा विश्वामित्रले आफ्नो सेना लिएर वशिष्ठ ऋषिको आश्रममा गए। विश्वामित्रले उनलाई प्रणाम गरेर त्यहीँ बसे। वशिष्ठ ऋषिले उनको यथोचित सत्कार गरे र उनलाई केही दिन आश्रममा बसेर आतिथ्य ग्रहण गर्ने अनुरोध गरे। आफूसँग रहेका धेरै सेनासहित बस्दा ऋषिलाई गाह्रो हुने ठानेर विश्वामित्रले विनम्रतापूर्वक बिदा हुने अनुमति मागे, तर वशिष्ठ ऋषिले अत्यधिक अनुरोध गरेको हुनाले केही दिनको लागि उनको अनुरोध स्वीकार गरे। वशिष्ठजीले नन्दिनी नामक गाईलाई आह्वान गरेर विश्वामित्र तथा उनका सेनाहरूका लागि ६ प्रकारका व्यञ्जन तथा सम्पूर्ण प्रकारका सुख-सुविधाको व्यवस्था गरिदिए। वशिष्ठको आतिथ्यले विश्वामित्र र उनीसँग आएका सबै मानिस प्रसन्न भए। नन्दिनी गाईको चमत्कार देखेर विश्वामित्रले त्यो गाई वशिष्ठसँग मागे, तर वशिष्ठले यो गाई कुनै हालतमा पनि दिन अस्वीकार गरे। वशिष्ठको यस्तो जवाफबाट विश्वामित्रले त्यो गाई जबरजस्ती पक्रेर ल्याउन आदेश दिए र उनका सैनिकले लौरोले हान्दै गाईलाई लैजान थाले। नन्दिनी गाई क्रोधित हुँदै सैनिकबाट आफ्नो बन्धन छुटाएर वशिष्ठकहाँ आएर विलाप गर्न थालिन्। वशिष्ठले भने, "हे नन्दिनी! यी राजा मेरा अतिथि हुन्, त्यसैले म यिनलाई श्राप दिन सक्दिनँ र यिनीसँग विशाल सेना छ, त्यसैले युद्धमा विजय हासिल गर्न पनि सक्दिनँ। म आफूलाई विवश अनुभव गरिरहेको छु।" उनका यी कुरा सुनेर नन्दिनीले वशिष्ठ ऋषिसँग आफूलाई लड्न अनुमति मागिन् र अन्य उपाय केही नदेखेपछि उनले अनुमति दिए। आज्ञा पाउनासाथ नन्दिनीले योगबलले अत्यन्त पराक्रमी मारक शस्त्रास्त्रहरूले युक्त योद्धा उत्पन्न गरिन् र तिनीहरूले शत्रुसेनालाई ध्वस्त पार्न थाले। आफ्नो सेनाको विनाश देखेर विश्वामित्रका सय पुत्र रिसाएर वशिष्ठलाई मार्न दौडिए। वशिष्ठले उनीहरूमध्ये एक जनालाई छोडेर सबैलाई भष्म गरिदिए। आफ्नो सेना तथा पुत्रहरूको विनाशपछि विश्वामित्र अत्यन्त दुःखी भए र छोरालाई राज्य सुम्पेर हिमालयको कन्दरामा कठोर तपस्या गरेर महादेवलाई खुसी पारेर उनीबाट दिव्य शक्तिहरूको साथै सम्पूर्ण धनुर्विद्याको ज्ञान प्राप्त गरे। ---- === नेपालका केही लोकप्रिय गोत्रहरू === * '''अगस्ति:''' ढुङ्गेल * '''अङ्गिरा:''' जोशी, शाही, सेढाईं, सौनक। * '''अत्रि:''' चापागाईं, मिश्र, अधिकारी, अर्याल (अर्जेल), वस्ती, गौतम, बम, भट्ट (पशुपति), खतिवडा, ओझा। * '''आत्रेय:''' देवकोटा, दुवाडी, अर्याल, भट्ट, खड्का (कालकोट), दुलाल, पौडेल, पोखरेल (पानी), शर्मा, सिग्देल, थापा (बगाले)। * '''उपमन्यु:''' मैनाली, ढकाल, बर्तौला, भट्ट (दुवाल), पाण्डे। * '''रवि:''' शाह, कल्याण (ठकुरी)। * '''साङ्ख्यायन:''' पाण्डे (देश)। * '''शाण्डिल्य:''' काफ्ले, पाठक, प्रसाईं, तिवारी। * '''भारद्वाज:''' अधिकारी, भट्ट (पुल्याई), चौलागाईं, देवकोटा, जमकरट्टेल, लोहनी, निरौला, पन्थी, पाण्डे (कुलेटा), पन्त, पोखरेल (दूध), शाही, शिवाकोटी, सुवेदी, थामी (अधिकारी), थपलिया, वाग्ले। * '''धनञ्जय:''' बस्याल, भुसाल, बस्नेत (खुलाल), बुढाथोकी (खुलाल), धमला, गुरागाईं, हुमागाईं, कार्की (खुलाल), खड्का (खुलाल), कुकुरकाटे, कुँवर, पङ्गेनी, रिजाल, थापा। * '''विश्वामित्र:''' भट्ट। * '''कश्यप:''' शाह, शाही, रायमाझी, घिमिरे, गोदार (थापा), कठायत, गर्तौला, अधिकारी (भँडारे, खिलचिने, कौबाली), बोगटी, बुढाथोकी (सोदारी), बडाल, भट्ट (कलौनी), मुस्याल, गड्तौला, हाडा, कुमाल, तिवारी। * '''कौण्डिन्य:''' आचार्य, न्यौपाने, प्याकुरेल, पनेरु, सापकोटा, भण्डारी (काला), सत्याल, मरासिनी, पराजुली, बास्कोटा, त्रिताल, खड्का, जोशी, खरेल, पाठक, थापा (बगाले र गाम्ले)। * '''कौशल्य:''' पाठक, थामी (क्षेत्री)। * '''कुण्डिन:''' त्रिताल, बन्जाडे। * '''कौशिक:''' खप्तडी (बस्नेत, खड्का, विष्ट, बुढाथोकी), रेग्मी, पाठक, गौडेल, भण्डारी, रिमाल, सन्जेल, शाही (सिँजापति), लामिछाने, ढुङ्गाना, धिताल, फुयाँल, तिवारी, माझी, लुइँटेल, थामी, पुडासैनी, बानियाँ, रघुवंशी, विडारी, बम (छत्याल ठकुरी), बास्ताकोटी। * '''गौतम:''' चन्द, बम (ठकुरी), दङ्गाल, पाण्डे (पल्लु), त्रिपाठी, तिवारी। * '''गर्ग:''' बास्तोला, लामिछाने, भुर्तेल, चुडाल, भट्ट (लामिछाने), खेतान, थापा (लामिछाने), रोका, गजुरेल। * '''गौतम:''' चन्द, त्रिपाठी, भेटुवाल, रिसाल, शाह (कास्की खण्ड)। * '''घृतकौशिक:''' सुतार, कार्की (सुतार), बराल, पण्डित, खनाल, नेपाल, बराइली। * '''पाराशर:''' धिमाल (खस), कार्की (लामा), कट्टेल, मरहट्टा। * '''वशिष्ठ:''' भण्डारी (थानसिङ्गे), भट्ट (ताप्लेजुङ्गे), हठ्ठराई, चालिसे, दवाडी, गैरे, गम्नाङ्गे, खरेल, मुडबरी, पाठक, राउत, सुयाल (घर्ती), सुयाल (थापा)। * '''माण्डव्य:''' बजगाईं, ज्ञवाली, पण्डित, कटुवाल, मास्के, पन्थी। * '''वत्स:''' भट्ट (नागर), दाहाल, दयाल, कँवर, खराली, लम्साल, राणा, रूपाखेती। ----[[विशेष:Contributions/&#126;2026-15382-66|&#126;2026-15382-66]] ([[प्रयोगकर्ता वार्ता:&#126;2026-15382-66|वार्तालाप]]) १९:०८, १२ मार्च २०२६ (नेपाली समय) == खसहरू ले कहिले देखि जनै लगाउन सुरु गरे ? के खसहरूले जनै लगाएको कारण खस सभ्यताको पतन भएको हो ? == @[[प्रयोगकर्ता:Rajendra bahadur basnet|Rajendra bahadur basnet]] [[विशेष:Contributions/&#126;2026-34443-02|&#126;2026-34443-02]] ([[प्रयोगकर्ता वार्ता:&#126;2026-34443-02|वार्तालाप]]) २१:५०, ११ जुन २०२६ (नेपाली समय) qnagxxvpbamc9jg6qkgxmspc659q3ju 1361176 1361175 2026-06-11T16:11:04Z ~2026-34443-02 79287 /* खसहरू ले कहिले देखि जनै लगाउन सुरु गरे ? के खसहरूले जनै लगाएको कारण खस सभ्यताको पतन भएको हो ? */ 1361176 wikitext text/x-wiki {{welcome}} -[[User:RajeshPandey|Rajesh]] ([[User talk:RajeshPandey|वार्ता]]) १७:०७, २० फेब्रुअरी २०१२ (युटिसी(UTC)) == खस जातिय  बस्नेत : गोत्र एक कुल देवता अनेक :राजेन्द्रबहादुर बस्नेत, Tulsipur 6 Dang == खस जातिय  बस्नेत : गोत्र एक कुल देवता अनेक                                                                                             राजेन्द्रबहादुर बस्नेत खस को हुन्? प्राचीन सिंजा राज्यअन्तर्गत बसोबास गर्ने खस जातिले अपनाएको संस्कृति नै मष्टो संस्कृति हो। खस राज्य विशाल भूभागमा फैलिएको थियो। यसमा कश्मीर, कुमाऊँ, तिब्बतको खारी प्रदेश, नेपालको कर्णालीसहितको पश्चिम भूभागदेखि गण्डकी प्रदेशसम्म यसको विस्तार भएको थियो। यसको बारेमा गुइसापे तुची (Giuseppe Tucci) ले आफ्नो पुस्तक Nepal: The Discovery of the Malla मा सिंजाको इतिहासको बारेमा लेखेका छन् — "The Empire of The khas is greater than my country Italy." कर्णाली वारिपारि विकसित भएर फैलिएको खस राज्यको आफ्नै मष्टो संस्कृति र सभ्यता थियो। खसहरूले विकास गरेको मष्टो संस्कृति र यसको प्रारूपको बारेमा उल्लेख गर्नुपूर्व खसहरू को हुन्, यसको बारेमा चर्चा गर्नु उपयुक्त हुन्छ। खसहरूको उद्गम स्थल कहाँ हो र यिनीहरू को हुन् भन्ने बारेमा विभिन्न मतहरू छन्। एउटा मत अनुसार एसिया माइनरबाट विभिन्न समूहहरू बसाइँ सर्ने क्रममा पूर्वतिर सर्दै आएको भन्ने भनाइ छ। अर्को मत उत्तर ध्रुवीय क्षेत्र नजिकबाट बसाइँ सराई गरेर आएको पाइन्छ। त्यसैगरी अर्को मत खसहरूको कश्मीर उद्गम स्थल मान्नेहरू छन्। अर्को महत्त्वपूर्ण मत अनुसार खसहरू टिग्रिस र युफ्रेट्स नदीको किनारमा विकसित मेसोपोटामिया/बेबिलोनियाको सभ्यतासँग जोडिन पुग्छन्। बेबिलोनियामा त्यहाँका प्रख्यात राजा हम्मुरावी (ई.पू. २१२३–२०८०) को शासनकाल पछि उनका उत्तराधिकारीहरू कमजोर हुँदै गएको र करिब ई.पू. १७०० आसपासमा कस्साइट्स (Kassites) ले आक्रमण गरी बेबिलोनियामा कब्जा गरेका थिए। कस्साइट्सहरू उत्तरी पहाडी प्रदेशका बासिन्दाहरू थिए। प्राचीन बेबिलोनियामा (ई.पू. १९९५–११५५) कुसाइटहरू (Kushites) ले राज्य गरेका थिए। तिनै काउस (Kaus), कुसाइट (Kushite), कस्साइट्स (Kassites) बाट खस बनेका हुन् भन्ने मानिन्छ। करिब ई.पू. १००० तिर बेबिलोनियाका कुसाइटहरू पूर्व लागेर विभिन्न ठाउँ हुँदै तिब्बततिर आए, जहाँ उनीहरूले करिब १५० देखि २०० वर्ष शासन गरेको पाइन्छ। यिनीहरू पाँचौँ शताब्दी ईस्वीसम्म तिब्बत र नेपालको कर्णाली क्षेत्रसम्म फैलिएका थिए भन्ने मानिन्छ। सिंजामा तिब्बतको खारी प्रदेशबाट आएका नागराजले शासन गर्नुपूर्व पाल वंशका राजाले राज्य गरेका थिए भन्ने कुरा पूर्णप्रसाद ब्राह्मणले उल्लेख गरेका छन्। ११औँ शताब्दी ईस्वीमा पश्चिम तिब्बत, यारी, खारी, पुराङबाट आएका नागराजले खस राज्यको स्थापना गरेका थिए। ई.पू. १७०० आसपासमा बेबिलोनिया कब्जा गरी लिने कस्साइट्सले मेसोपोटामियामा पहिलोपटक घोडा ल्याएका थिए। घोडचढी गरेर युद्ध गर्दा उनीहरूलाई युद्धमा विजय हासिल गर्न निकै सहज भएको थियो। पछि कस्साइट्सलाई हराएर हिट्टाइट्स (Hittites) ले बेबिलोनियामा शासन गरे। हिट्टाइट्स पछि असीरियनहरूले बेबिलोनियामा शासन गरे। उनीहरू असुर सहर (टिग्रिस नदी किनार) का निवासी थिए। उनीहरूका असुरबनिपाल र सेनाचेरिव प्रसिद्ध राजा थिए। कसै-कसैले तिनै असुरबनिपालसँग 'बान्नी मष्टो' लाई जोड्ने गर्दछन्। असुर प्राचीन असीरियाको धार्मिक राजधानी थियो। प्राचीन मेसोपोटामिया (हालको इराक) को टिग्रिस नदीको पश्चिम किनारमा असुर साम्राज्यको विकास भएको थियो। करिब ई.पू. २६००–२५०० देखि करिब ई.पू. १४०० सम्म यो समृद्ध सहर थियो। असुर यो सहरको मुख्य देवता थिए जो त्यहाँका सबैभन्दा शक्तिशाली र असीरियन साम्राज्यको संरक्षक समेत मानिन्थ्यो। असुरको पुरातात्त्विक सर्वेक्षण जर्मन पुरातत्त्वविद् फ्रेडरिक डिलिच र पछि वाल्टर आन्द्रे (Walter Andrae) ले गरेका थिए। जर्मन ओरिएन्टल सोसाइटीले पनि यसमा कार्य गरेको थियो। यहाँ १६०० भन्दा बढी क्युनिफर्म (Cuneiform) लिपि अंकित माटोका भाँडाहरू भेटिएका छन्। विभिन्न विद्वान्हरूले तिनै असुरबनिपालसँग 'बान्नी मष्टो' लाई जोड्ने गर्दछन्। मेसोपोटामियामा त्यस समयमा विभिन्न देवताहरूको पूजा गरिन्थ्यो। त्यसबेला मुख्य रूपमा इया (Ea), एन-लिल (En-Lil), उतु (Uta), मर्दुक (Marduk) आदि देवताहरूको पूजा गर्ने गरिन्थ्यो। बेबिलोनियाको यसै मर्दुकलाई खसहरूको मुख्य देवता मानेर मर्दुकबाट मष्टो भएको हो भन्ने एकथरी मत पाइन्छ। कतिपयले बेबिलोनियाबाट आएको मष्टो भएकाले यसको नाम 'बाबिरो मष्टो' रहन गएको समेत मान्दछन्। बेबिलोनिया बासीहरू शक्तिका पनि उपासक थिए। उनीहरू इस्तार (Istar) देवीको पूजा गर्दथे। खस जातिहरूले बेबिलोनियामा शासन गर्दा टुर्गु (Turgu) को पूजा गर्दथे। टुर्गु शब्दको अपभ्रंश भएर दुर्गा हुन गएको हो भन्ने मत पनि पाइन्छ। यहाँ विभिन्न देव-देवीका मन्दिरहरू बनेका थिए। सेनाचेरिव (ई.पू. ७०४–६८१) को शासनकालमा मात्र ३४ वटा मन्दिर बनेका थिए। यहाँका प्रमुख राजाहरूमा टिगलाथ-पिलेसर तृतीय, सार्गन द्वितीय, सेनाचेरिव र एसरहडोन प्रमुख थिए। अर्को महान् राजा असुरबनिपाल थिए, तिनै असुरबनिपालबाट बान्नी मष्टो र बेबिलोनियाबाट बाबिरो मष्टो खसहरूमा परम्परागत रूपमा आएको भन्ने मत पनि पाइन्छ। असुर सहरमा बेबिलोनियाको दमन पछि त्यहाँका मानिसहरू (असुर) लाई हेयको दृष्टिले हेरिने र क्रूर रूपमा प्रस्तुत गर्ने र आफूलाई देवत्वकरण गर्ने कार्य उनीहरूले गर्दथे। पछि भारतीय भूभागको तल्लो क्षेत्र (मैदानी क्षेत्र) मा पकड जमाएर सैन्धव सभ्यताको विनाश गर्ने कथित आर्यहरूको समूहले पराजित समूहहरूलाई बेबिलोनियाले असुरहरूमाथि विजय गरेर उनीहरूमाथि विजय गरेको अहङ्कार र असुर शब्दलाई घृणा र हेपाइको रूपमा प्रयोग गरे जस्तै गरेर प्राचीन भारतमा पनि पराजित माथि असुर शब्द त्यसै रूपमा प्रयोग गरेको पाइन्छ र पराजितलाई असुरको आवरण लगाएर आफूलाई देवत्वकरण गरेको पाइन्छ। उनीहरूले साहित्य र शिक्षामा जमाएको पकडले उनीहरूमा यस्तो प्रवृत्ति आयो। खसहरूको बारेमा वैदिक साहित्यमा खासै उल्लेख नहुनु र असुरलाई कतै दानव र कतै देवताको रूपमा उल्लेख गर्नुबाट उनीहरू पहिले खसहरूलाई उपेक्षा मात्र होइन खसले पूजा गर्ने शिवलाई समेत अत्यन्त न्यून कोटीको देवताका रूपमा उल्लेख गरेको पाइन्छ। असुर कुनै दानव नभएर असुर सहरका बासिन्दा थिए। जसको देवताको नाम असुरबाट त्यस सहरको नाम समेत असुर राखिएको थियो। असुर (अस्सूर) प्राचीन मेसोपोटामिया स्थित नव असीरियन साम्राज्यको राजधानी थियो। यसै क्षेत्रमा अहुरमज्दा नामक प्रसिद्ध देवता थिए। प्राचीन इरानी पन्थका यी देवता अहुरमज्दाबाट मज्दाको अपभ्रंश भई मष्टो हुन आएको हो भन्ने एकथरीको मत पाइन्छ। अहुरमज्दालाई संस्कृतमा असुर महत भनेर उल्लेख गरेको छ। पारसी पन्थका संस्थापक जरथुस्त्रले यी देवतालाई अजन्मा, सर्वज्ञ परमेश्वर भनेका छन्। यिनलाई अहुरमज्दा बाहेक ओहरमज्द, होउरमज्द, हुर्मुज, अरमज्द र अज्जन्दार नामबाट पनि चिनिन्छन्। ऋग्वेदमा 'असुर महत' को वर्णन गरेको पाइन्छ। मेसोपोटामियाको सभ्यताको विकासको उत्कर्षको समयमा विभिन्न देव-देवीहरूका मूर्तिहरूको निर्माण र पूजा गर्ने परम्परा विकसित अवस्थामा थियो। यसको प्रारम्भ कहिलेदेखि भयो भन्ने प्रश्नको उत्तर भने अत्यन्तै जटिल छ। सभ्यताको आदिम युगमा जसलाई पाषाण युग भन्ने गरिन्छ, मानिसहरूमा धर्मको भावनाको विकास भएको थिएन। उनीहरूले मानिसको मृत्यु पछि शवलाई त्यत्तिकै छोडेर जान्थे जो पशुपन्छीको आहारा बन्दथ्यो। मध्य पाषाण युगमा आएर शवलाई गाड्ने कार्य प्रारम्भ भएको थियो। विभिन्न उत्खननबाट शवहरूको अस्थिपञ्जरको शिर नजिक राखिएका पाषाण सामग्रीहरूबाट यो कुरा थाहा हुन्छ। यसै युगबाट अन्त्येष्टिमा गरिने अनुष्ठानहरूको प्रारम्भ भएको अनुमान गर्न सकिन्छ। यसैबाट मानिसमा धार्मिक चेतनाको प्रारम्भ भएको अनुमान गर्न सकिन्छ। उत्तर पाषाण युगमा धार्मिक अनुष्ठानको साथसाथै विभिन्न अन्धविश्वासको पनि विकास भएको थियो भन्ने कुरा त्यसबेलाका उत्खननबाट प्राप्त अवशेषहरूबाट थाहा पाउन सकिन्छ। सभ्यताको विकासको साथसाथै मानिसहरू समूहमा बस्ने प्रचलन सुरु भएको थियो। भारतमा गरिएको एउटा अध्ययनले भारतमा सबैभन्दा पहिले 'नेग्रिटो' जातिले बसोबास गरेका थिए। त्यसपछि प्रोटो-अस्ट्रेलोइड वा निषाद आएका थिए। यो जातिको पछि आएका आर्यहरूको संस्कृतिमा विलिन भएको थियो। यी जातिहरू टोटमवादी जातिका थिए। यिनीहरूले नाग, गोही, बाँदर आदिको पूजाको सुरुवात गरेका थिए। भारतमा प्रोटो-अस्ट्रेलोइड जातिले धार्मिक भावनाको सुरुवात गरेका थिए। निषाद पछि द्रविड जाति भारतमा भूमध्य सागरीय क्षेत्रबाट आएका र यिनीहरूले सैन्धव सभ्यता र संस्कृतिको विकास गरेका थिए। सैन्धव धर्मको बारेमा लेख्य सामग्री प्राप्त नभए पनि उत्खननबाट प्राप्त सामग्रीबाट यिनीहरू मातृशक्तिका उपासक थिए। जसमा अनेकौँ नारी मूर्तिहरू समेत प्राप्त भएका छन्। मोहन्जोदारोमा उत्खननबाट एउटा परम पुरुषको कल्पना गरिएको एक मुद्रा जसमा एक नग्न पुरुष योगासन मुद्रामा बसेका छन्। यी योगीका ३ मुख छन् शिरमा शृङ्ग-मुकुट अथवा त्रिशूल अंकित छ। योगीको बायाँतिर एउटा गैँडा र भैँसी र दाहिनेतिर एउटा हात्ती र बाघ छ अगाडि तिर मृग छ। यो आकृति हेर्दा खसहरूसँग शिवलाई जोड्न मिल्ने शैवपाशुपत स्वरूपको यो आकृति देखिन्छ। मार्शलले यसलाई शिवको मुद्रा मानेका छन्। वैदिक आर्यहरू भारतमा आउनु पूर्व विकसित यो सभ्यता र मष्टोलाई शिवसँग जोड्ने मतको आधारमा खस सभ्यताको प्रभाव सैन्धव सभ्यतामा परेको अड्कल गर्न सकिन्छ। खसहरूको उद्गम स्थल बारे विभिन्न विद्वान्हरूका फरक फरक मतहरू छन्। पौराणिक मत अनुसार खस क्षेत्रीहरूको उद्गम थलो हुम्लाको शैपाल र बझाङ थियो भन्ने एकथरीको मान्यता छ। उनीहरू अनुसार खस क्षेत्रीका पुर्खा कैलाशबाट आएको र मष्टोलाई कैलाशमा उत्पन्न भएको र त्यहीँबाट कर्णाली उपत्यकामा आएर अन्यत्र फैलिएको मान्दछन्। इन्डो-आर्यन ओरिजिन थ्योरी (Indo-Aryan Origin Theory) अनुसार हिन्दू साहित्यमा खसहरूको उल्लेख पाइन्छ। आइरिस भाषाविद् सर जी.ए. ग्रियर्सनले आर्य भाषिक हिमालयको तल्लो भागदेखि कश्मीर सम्मका बासिन्दाहरू महाभारतमा उल्लिखित खसका सन्तान हुन् भन्दछन्। इतिहासकार बालकृष्ण शर्मा र नृतत्त्वशास्त्री डोरबहादुर विष्ट खसलाई इन्डो-युरोपियन मूलका मान्दछन्। खसहरू हालको कश्मीरबाट आएका र त्यहाँका स्थानीय खस/कसबाट त्यो ठाउँ कश्मीर रहन गएको मान्दछन्।   करिब ई.पू. २००० तिर खसको एउटा समूह इरानतिर र अर्को समूह सतलज नदीको पूर्वतर्फको पहाडी भागदेखि भेरी नदीसम्म फैलिएर बसे। बालकृष्ण पोखरेल खसलाई वैदिक आर्य मान्दैनन्। उनीहरू पछि गुर्जर, पल्लव, शक जस्तै आर्य बनेका मान्दछन्। आइरिस भाषाशास्त्री जर्ज अब्राहम ग्रियर्सनले खसहरू संस्कृत र इरानी भाषा समूहका आर्य मूलका क्षत्रिय जातिका योद्धाहरू हुन् भन्ने मत राख्दछन्। खसहरूको उद्गमको बारेमा अर्को सशक्त मत झाङ-झुङ (Zhang Zhung) सभ्यतासँग जोडिएको छ। यसलाई झाङ-झुङ सभ्यताको सिद्धान्तको रूपमा चिन्ने गरिन्छ। यो सिद्धान्त अनुसार खसहरूको सम्बन्ध तिब्बतको प्रारम्भिक उद्भव कालदेखि तिब्बती साम्राज्यको उत्थानसम्म खसहरू जोडिएका छन्। कुनै-कुनै वर्णनमा झाङ-झुङ संस्कृति खससँग सम्बन्धित मानिएको छ। केही विवाद पश्चात् खस मल्ल अस्तित्वमा आएका थिए जो तिब्बतबाट पश्चिम नेपालमा आएका मानिन्छन्। किरातहरूको प्रसिद्ध धार्मिक ग्रन्थले खसहरू प्राचीन चीनको तारीम बेसिन (Tarim basin) बाट नेपाल आएका र त्यो बेला नेपालमा किरातहरूको शासन रहेको उल्लेख छ। खसहरूको तारीम बेंसीमा रहेको खसगर (Khasgar) नामक किल्लामा लघु युची कुषाणले आक्रमण गरी त्यहाँबाट भगाएपछि उनीहरू नेपालमा आएको र किराती राजाले त्रिशूली नदीको पश्चिमतिर बसोबास गर्न दिएको र त्यहीँबाट पश्चिम कश्मीरसम्म फैलिएको उल्लेख छ। तिब्बती मान्यतामा पनि खसहरू तिब्बती साम्राज्यसँग जोडिएका थिए। झाङ-झुङ सभ्यता अन्तर्गत यात्से किंगडम (Yaste kingdom) लाई खस/यात्से वा चल्ला/मल्ल वंशको रूपमा चिनिन्थ्यो। कर्णाली प्रदेशमा खस राज्यको स्थापना गर्ने मानिएका नागराज यसै वंशका मानिन्छन्। उनको काल करिब ११औँ शताब्दी मानिन्छ। यात्सेले सन् १२२० तिर जुम्ला र गढवाल विजय गरेको, सन् १२३५–१२३९ बीच गङताङ (Gangtang) माथि विजय हासिल गरेको पाइन्छ। राजा अशोक चल्ल/कल्लले सन् १२५० तिर दक्षिणी सीमा विस्तार गरेका थिए। खसहरूले सन् १२८८ र सन् १३३४ मा काठमाडौँ आक्रमण गरेका थिए। सन् १३२८ पछि पतनोन्मुख भएको खसहरूको राज्य सन् १३७० सम्म पुग्दा पूर्ण रूपमा समाप्त भयो।   खसहरूमा सुरुमा तिब्बती संस्कृतिको ठुलो प्रभाव थियो। खसहरू बसोबास गर्ने सिंजा, जुम्ला, गढवाल र वरिपरिका क्षेत्रहरूमा यसको व्यापक प्रभाव थियो। पछि हिन्दू आर्य शासकहरूको दबदबा बढेको र शासकहरूले पनि उनीहरूका मान्यता अवलम्बन गर्दै गएकाले खसहरूले अवलम्बन गर्दै आएका मान्यताहरूमा क्षयीकरण हुँदै गए। ________________________________________    खसहरूले गुगे नजिकको खसहरूले गुगे नजिकको पाराङमा शासन गर्दथे, पछि तिनीहरू पहिलो र दोस्रो शताब्दीको बीचमा थाक हिमाल र च्याङला  हिमाल को बीचबाट हुम्लामा आएका थिए र त्यहीँ तिनीहरूले पहिलो राज्य स्थापना गरेका थिए।". खस र मष्टो संस्कृति: ऐतिहासिक पृष्ठभूमि प्राचीन सिंजा राज्यको गुगेमा अवस्थित रहेको मल्लवंशका पुर्खाहरू दक्षिण पाराङको पश्चिमी पहाडी क्षेत्रमा राज्य गरेको पाइन्छ, जसको ल्हासा राजपरिवारसँग सम्बन्ध रहेको थियो। पछि गुगेले आफूलाई स्वतन्त्र गरेको थियो। त्यहाँका शासकहरूमध्ये नागदेव र उनका पुत्र कपिललाई खस (Yatse) वंशको संस्थापक मानिन्छ। तिब्बती मूलका भए तापनि नेपालमा आउँदा हिन्दू-आर्य तथा बौद्ध दुवै संस्कृतिको प्रभावले यिनीहरूको जीवनशैली प्रभावित थियो। खसहरूले गुगे नजिकैको पुराङमा शासन गर्दथे। पछि उनीहरू पहिलो र दोस्रो शताब्दीको बीचमा थाक हिमाल र च्याङ्गला हिमालको बीचबाट हुम्लामा आएका थिए र त्यहीँ उनीहरूले पहिलो राज्य स्थापना गरेका थिए। त्यसभन्दा पहिले यिनीहरूले चीनको तारिम उपत्यकामा खसगर (Khasgar) राज्यको स्थापना गरे। त्यसपछि ताक्लाकोटमा आफ्नो कब्जा गरे। खसहरूको उद्गमको सन्दर्भमा अर्को मत अनुसार खसहरू 'शक' जातिबाट आएका हुन् भन्ने छ। राहुल सांकृत्यायन खस र शकलाई एउटै जातिका दुई समूह मान्दछन्। शकहरू ई.पू. को पहिलो शताब्दी पहिले नै आएको र खसहरू हिमाली क्षेत्रतर्फ फैलिएको मानिन्छ। ओमचन्द्र हण्डा लगायत कतिपय विद्वान् यसै सिद्धान्तका पक्षधर छन्। दैलेखको संवत् १०३८ (९८१ ई.) को पहिलो नेपाली भाषाको शिलालेखबाट १००० ई.पू. देखि ५०० ई.पू. सम्म खसहरू नेपालमा आइसकेका थिए भन्ने अनुमान गर्न सकिन्छ। खसहरूको समृद्ध राजनीतिक र नगर सभ्यताको उत्कृष्ट चरण बेबिलोनियामा जुन समयमा कस्साइटहरूको शासन चलिरहेको थियो (१५९५–११५५ ई.पू.), त्यसै समयमा अर्थात् करिब १५०० ई.पू.–६०० ई.पू. (जसलाई वैदिक काल भनिन्छ), खसहरूको विभिन्न समूह बेबिलोनिया क्षेत्रबाट नयाँ ठाउँहरूमा समूह-समूहमा फैलिएर अगाडि गइरहेका थिए। तीमध्येकै एउटा ठुलो समूह इरान, अफगानिस्तान, कश्मीर हुँदै भारतको मैदानी भूभागतर्फ अगाडि बढ्यो। त्यो समूहले आर्य संस्कृतिको विकास गर्यो, वैदिक मन्त्रको रचना गर्यो, आख्यान र उपनिषद्हरूको रचना गर्यो; त्यो समूहले आफूलाई वैदिक आर्यको रूपमा स्थापित गर्यो। ६०० ई.पू. देखि २०० ई.पू. सम्म आउँदा दर्शन, उपनिषद्को रचना, रामायण र महाभारतबाट मानिस र देवताका सम्मानित विचारहरू र विरचित कृतिहरू रचिए। विभिन्न धार्मिक विचार र सम्प्रदाय (बौद्ध, जैन, वैष्णव) अस्तित्वमा आए। २०० ई.पू. बाट मौखिक कुरालाई सम्झन गाह्रो हुने भएकाले यसलाई संक्षिप्त रूपमा बुझ्नका लागि सूत्र रचनाको प्रारम्भ भयो। त्यसका लागि टीका र २०० ई.पू. पश्चात् विभिन्न दर्शन सूत्र, ग्रन्थ भाष्य टीका रचना भए र धार्मिक आन्दोलनले समाजमा ठुलो प्रभाव छोड्न गयो। हरिभद्रको 'षड्दर्शन समुच्चय' छैटौँ शताब्दीमा, समन्तभद्रले 'आप्तमीमांसा', बौद्ध दर्शनका विद्वान् आचार्य भावविवेकले मीमांसा, सांख्य, वैशेषिक र वेदान्तको आलोचना गरिएको 'तर्क ज्वाला' को रचना गरे। १४औँ शताब्दीतिर बौद्ध धर्मको अत्यधिक प्रभाव र वैदिक धर्मप्रतिको प्रहारबाट त्यसलाई बचाउन शंकराचार्य आक्रामक रूपमा अगाडि आए र उनले 'सर्व सिद्धान्त सार संग्रह' नामक पुस्तकको रचना गरे। इरान, अफगानिस्तान, कश्मीर हुँदै भारतको समथर भूभागतर्फ नगएर अफगानिस्तान, कश्मीर हुँदै हिमालयको काख हुँदै पूर्व नेपाली भूभागतर्फ फैलिएको खस (कस्साइट्सको शाखा) आफ्नो आदिम रीतिथिति, संस्कृति र मूल्यमान्यतामा निरन्तर लागिरह्यो। त्यही समूह खस जाति थियो। यिनीहरू बेबिलोनिया र असुर सहरमा विकसित सभ्यता र देवताको विरासत साथै कालान्तरमा बौद्ध संस्कृति तथा धार्मिक प्रभावका कारण खसहरूको संस्कृतिमाथि वैदिक खस आर्यको अपहेलित व्यवहार र आफूलाई श्रेष्ठ ठहर्याउने दम्भका कारण खसहरूका देवता मष्टोलाई उनीहरूले देवताको स्थान नदिएको र वेद तथा उपनिषद्हरूमा कतै उल्लेख नगरेको कुराबाट स्पष्ट हुन्छ। त्यति मात्र होइन, शिव सम्भवतः अवैदिक खसका देवता हुन् जसलाई सैन्धव सभ्यतामा अपनाएर एउटा महत्त्वपूर्ण देवताको रूपमा स्वीकार गरिएको शैव पाशुपताकृति युक्त सामग्री प्राप्त छ। वैदिक साहित्यमा शिवलाई तल्लो दर्जाको महत्त्वहीन देवताको रूपमा देखाइएको छ। पछि वैदिक संस्कृतिमाथि चारैतिरबाट प्रहार भएपछि खसहरूसँग वैदिक खसहरू पराजित भए र खसहरूलाई क्षत्रीयको श्रेणी र सर्वशक्तिमान् देवताको रूपमा शिवलाई मान्यता प्राप्त भएको मानिन्छ। शंकराचार्यको उदयपछि (१४औँ शताब्दी पछि) नेपाली तथा उत्तराखण्ड, कुमाऊँ र कश्मीरका क्षेत्रमा फैलिएका खसहरूको अहिले सम्म पनि आफ्नै समृद्ध मष्टो परम्परा र संस्कृतिमाथि ठुलो प्रहार गरियो र खस पहिचान मास्ने प्रयास गरियो। 'खस' शब्द नै अपमानित शब्दको रूपमा प्रचार गर्न सुरु गरियो। खसहरू पनि बिस्तारै वैदिक खस आर्यहरूका धार्मिक, सांस्कृतिक र सामाजिक व्यवहार अवलम्बन गर्दै आफ्ना आदिम युगदेखि सञ्चित गरेर जोगाएका परम्परा छोड्दै गए र नयाँ व्यवहारहरू अवलम्बन गर्न थाले। डा. हरिश लखेडाले संविधानमा अहिले बाहुन, क्षेत्री, ठकुरी, संन्यासीलाई नेपालमा 'खस आर्य' मा सूचीकृत गरिएको बताउँछन्। People of Nepal का लेखक डोरबहादुर विष्टले दलितहरूलाई पनि खस हुन् भनेका छन्। कामी, दमाई, सार्कीहरूले पनि मष्टो देवताको पूजा गर्दछन्। डा. विपिन अधिकारीले नेपालमा अहिलेका क्षेत्री, बाहुन, कामी, ठकुरी, सार्की, संन्यासी, बादी, दमाई, गाईने र अन्य खसमा पर्दछन् भन्दछन्। इतिहासकार बालकृष्ण शर्मा र डोरबहादुर विष्ट खस/कसलाई युझी मूलका मान्दछन्। इतिहासकार बाबुराम आचार्य खस ऐरावतको एउटा उपशाखा (कविला) हो जसको उत्पत्ति इडावर्त हालको कश्मीरबाट भएको मान्दछन्। खसहरू तेस्रो शताब्दी ई.पू. मा इडावर्तमा रहन्थे। खसको मूल अर्थ 'राजा' वा 'क्षेत्री' अर्थात् 'योद्धा' भन्ने हुन्छ। उनीहरूको बसोबासको स्थल 'खस' बाट कश्मीर रहेको र दोस्रो शताब्दी ई.पू. मा खसको एउटा समूह कजाकिस्तान र अर्को समूह सतलज नदीको पूर्व हुँदै नेपालतर्फ गयो। बालकृष्ण पोखरेल खसहरूलाई वैदिक आर्य मान्दैनन्। प्रा.डा. गोविन्द सिंहले खसहरूमा विधवा विवाह प्रचलित थियो भन्ने मान्यता राख्दछन्। उनीहरूमा खुला समाज थियो। स्त्रीको उच्च स्थान थियो। खसको आर्यको जस्तो जकडन र बन्धनमा बाँधिएको समाज थिएन भन्ने कुराको उल्लेख गरेका छन्। बस्नेत को हुन्? माथि उल्लिखित खसहरूका विभिन्न समूहहरू जो स-साना समूहमा नेपालको पश्चिमी पहाडी क्षेत्रमा फैलिएको हिमालयको काखमा अवस्थित भूभागमा बस्ने खसहरूको एउटा समूह बस्नेत हो। आदिकालदेखि आफ्नै शौर्य, पराक्रम, वीरतापूर्ण र गौरवशाली इतिहास बनाउन सफल भएका कारण बस्नेतहरू इतिहासका विभिन्न कालखण्डदेखि नेपालको एकीकरणको लागि युद्धका मैदानमा अभूतपूर्व उत्साह र साहसले इतिहासमा स्वर्ण अक्षरमा नाम अंकित गर्न सफल जाति हुन्। राजा-रजौटा र राज्य सञ्चालनका प्रमुख जिम्मेवारीहरूका लागि बस्नेत सधैँ नै राज्यको सुरक्षा र सञ्चालनको निम्ति अनिवार्य जस्तै भूमिकामा रहे। "खप्तडी बस्नेतको मूल थलो खप्तड लेक (खेचराद्री) बडीमालिका पश्चिमपट्टी सेती अञ्चलमा अछाम, बझाङ, बाजुरा, थलारा, दार्चुला, बैतडी, डोटीको माझ पूर्व-पश्चिम लम्बायमान अवस्थामा रहेको स्थान हाल मानव विहीन छ। खप्तडी बस्न्यातको अवस्थन खप्तड (खेचराद्री) सेती अञ्चल बडीमालिकाको दायाँ पट्टी छ" भन्ने कुरा योगी नरहरिनाथले बताउनुभएको छ। खप्तड लेकतिर मोटो खालको भुईँमा कालो छिट्का मिसिएको मोटो टुप्पा मसङ्ग्रिँदै गएको निगालो बाँस प्रशस्त पाइने र त्यहीँको नेटो (डाँडाको सिरान) अर्थात् बाँस पाइने नेटो "बाँसनेटो" मा बस्ने मानिसलाई बाँसनेटो — बासनेता — बस्न्याता — बस्न्यात — बस्नेत भएर बस्नेत भएको हुन सक्दछ। आजभोलि पनि गाउँघरमा यस्ता प्रशस्त उदाहरण पाइन्छ, जस्तै: तुलसीपुरबाट बसाइँ सरेर आएको तुलसीपुरे, दैलेखबाट आएको दैलेखी, सल्यानबाट आएको सल्यानी आदि। मध्यकालीन राज्य व्यवस्थामा दरबार सम्बन्धी मुद्दामामिला हेर्ने, बस्ती बसाउने र व्यवस्थित गर्ने जिम्मेवारी पाएको मानिसलाई 'बस्नेत' भन्ने गरिन्थ्यो भन्ने मत तथ्यको नजिक लाग्छ। यसको कारण बस्नेत थरका मानिसहरूको गोत्र एउटै नहुनु पनि हो। खप्तडी बस्नेतको गोत्र कौशिक, श्रीपाली बस्नेतको गोत्र भारद्वाज, खुलाल बस्नेतको गोत्र धनञ्जय र लामिछाने बस्नेतको गोत्र गर्ग हुनाले बस्नेत जातीय भन्दा पदिय उपाधि थियो, जो विभिन्न थर र गोत्रका मानिसहरूलाई कार्यदक्षता, योग्यता र जिम्मेवारी वहन गर्न सक्ने क्षमताको आधारमा प्रदान गर्ने गरिन्थ्यो भन्ने अनुमान गर्न सकिन्छ। श्रीपाली बस्नेतहरूले आफ्ना पुर्खाहरू श्रीपाल राज्यका श्रीपुर शाहीका वंशज मान्दछन्, जसबाट विभिन्न थर र गोत्रका मानिसहरू बस्नेत उपाधिबाट विभूषित भएको र कालान्तरमा विभिन्न थर र गोत्रका मानिस बस्नेत भएको हुन सक्छ भन्न सकिन्छ। खप्तडी बस्नेतको कुलदेवता दाह्रेमष्टो, श्रीपाली बस्नेतको कुलदेवता आदि मष्टो लिसिसाँकोटी, खुलाल बस्नेतको कुलदेवता दाह्रेमष्टो र लामिछाने बस्नेतहरू मध्य भोजपुरको अघेरीतिर कैलाशमष्टो मान्दछन् भने तेह्रथुमतिरका लामिछाने बस्नेतहरू महामष्टो कुलदेवता मान्ने गर्दछन्। मष्टो को हुन्? मष्टो सिंजा साम्राज्य अन्तर्गतका खस जातिले आफ्नो कुलदेवताको रूपमा पूजा-आराधना गर्दै आएका देवता हुन्। प्राचीन सिंजा राज्य अन्तर्गतका क्षेत्री, बाहुन, ठकुरी लगायत कतिपय अन्य जातिका कुलदेवता मष्टो हुन्। तत्कालीन सिंजा राज्य नेपाल खाल्डोदेखि कश्मीर, कुमाऊँ, तिब्बतको खारी सम्म फैलिएको थियो। मष्टो सम्बन्धी विभिन्न मतहरू छन्। मष्टोका विभिन्न भेदहरू पनि छन्। मुख्य रूपमा मष्टो २ किसिमका छन्: १. दाह्रे मष्टो २. दुधे मष्टो मष्टोको पूजा घरमाण्डौ र वनमाण्डौमा गरिन्छ। घरमाण्डौमा मूल धामी बस्ने स्थान जसलाई 'गादी' भनिन्छ, त्यसमा सेतो कपडा लगाएका झाँक्री, चमर, सोँटा सहित मष्टोको थानमा धामी गएपछि देउता चढ्दछन् र उनीहरू काँप्न थाल्दछन्। पश्चिम नेपालको हिमाली क्षेत्र 'जडान' र पहाडी क्षेत्र 'खसान' को नामले चिनिन्छ। यही खसान क्षेत्रमा खस भाषा र मष्टो संस्कृतिको विकास भएको मानिन्छ। तत्कालीन खस देशमा बस्ने बाहुनहरूको कुलदेवता मष्टो हुन्। भारतमा मुसलमान आक्रमण पछि भागेर नेपाल प्रवेश गरेका र हुकुमी शासन कालमा हुकुम प्रमाङ्गीबाट खस बनेका खसहरूको कुलदेवता मष्टो हुँदैनन् भन्ने कुरा डा. जगमान गुरुङ मान्दछन्। उनको अनुसार सम्पूर्ण खसहरूका कुलदेवता मष्टो हुन्। मष्टोका पिता-माता को हुन् भन्ने उल्लेख कतै पाइँदैन। मुगुतिर एउटा किंवदन्ती प्रचलित छ। उक्त मत अनुसार मष्टोको उत्पत्ति कैलाश मानसरोवर क्षेत्रमा भएको थियो। महिषासुर राक्षसले तपस्या गरी ब्रह्माजीलाई रिझाएर पुरुषको हातबाट नमर्ने वरदान मागेको र वरदान पाएपछि देवताहरूलाई पराजित गरी इन्द्रपुत्रलाई पराजित गर्न पिछा गर्दा उनी भागेर हिमवत् खण्ड आउँदा मष्टोदेवको जन्म भएको थियो। कोही-कोहीले मष्टोलाई भगवान् शिवको अंशको रूपमा पनि हेर्ने गर्दछन् र १२ मष्टोका मूल स्थानमा शिवलिङ्गको स्वरूपको अवस्थितिले समेत उक्त कुरालाई औचित्यपूर्ण ठहर्याउने प्रयास गरिन्छ। अर्को मत अनुसार मष्टोलाई स्वर्गका राजा इन्द्रका पुत्र मान्ने गरिन्छ। "स्वर्गका राजा इन्द्र, धर्तीका राजा मष्टो, पातालका राजा नागराज" भन्ने उक्ति प्रचलित छ। मष्टो निराकार हुन्छन्। मष्टो शब्दको उत्पत्ति 'मस्तक' (शिर) बाट भएको योगी नरहरिनाथले मान्दछन्। उनले सुरुमा मष्टो एउटै भएको र पछि मष्टो देवता थपिँदै जाँदा बाह्र मष्टो भन्न थालिएको र बाह्र मष्टोलाई पछि वराह मष्टो, वारामष्टो समेत भन्ने गरिएको थियो। मष्टोको वाहन घोडा हो। भेडा, चितुवा र झार पनि मष्टोका वाहन हुन्। मेसोपोटामियाको मुख्य देवता Marduk (मर्डुक) बाट मष्टो भएको र मेसोपोटामिया स्थित नव-असीरियन साम्राज्यको राजधानी असुरमा स्थित तत्कालीन विख्यात देवता अहुरमज्दाको 'मज्दा' को अपभ्रंश भएर मष्टो भएको भन्ने मत छ। करिब १७०० ई.पू. तिर पहिलोपटक मेसोपोटामियामा घोडा ल्याएर आक्रमण गरी त्यहाँ विजयी भएर शासन गर्ने कस्साइट्स (खस) र उनीहरूको वाहन घोडा र कस/खसको देवता अहुरमज्दाबाट मष्टो बनेका देवताको वाहन घोडा हुनु संयोग मात्र नभई कस्साइट्सबाट खस र अहुरमज्दाबाट मष्टोको निकट र निरन्तरताको सम्बन्ध देखिन्छ। वैदिक सनातन धर्मको विकास हुनुपूर्व नै नेपालमा मष्टो धर्मको विकास भइरहेको भए तापनि हालसम्म मष्टो धर्मको विषयमा कुनै पनि प्राचीन हस्तलिखित सामग्रीहरू प्राप्त भएका छैनन्। तर मष्टो धर्म, देवता र यसको उत्पत्तिका सन्दर्भमा विभिन्न किंवदन्ती, मिथक र कहावतहरू भने प्रशस्त रूपमा पाइन्छन्। प्राचीन बेबिलोनिया/मेसोपोटामियामा मष्टोको पूर्व रूपलाई 'अहुरमज्दा' भनिन्छ र मष्टो धर्म मान्ने प्रथम व्यक्ति आदिमनाथ हुन्। आदिमनाथलाई आदिनाथ भनिन्छ। भगवान् शिवले अलकापुरी शक्तसिंह (बहादुर) लाई दिए र उनै शक्तसिंह देवताका राजा इन्द्र तथा मष्टो भए भन्ने एउटा मत पनि छ। 'मरुत' शब्दको अर्थ वायु हुन्छ, यिनै वायु देवता मरुतबाट मरुत—मउत—मष्ट हुँदै मष्टो भएको भन्ने भनाइ पनि पाइन्छ। मान्छेले मान्ने देवता भएकाले मान्ठ, मान्ठा, मन्ठा हुँदै मष्टो भएको अनुमान सत्यमोहन जोशीको छ। योगी नरहरिनाथले मष्टोलाई महेश्वरको अंश अवतार/अष्टमूर्ति महादेव शिव (पृथ्वी, जल, तेज, वायु, आकाश, चन्द्र, सूर्य र आत्मा) महा+अष्ट भुजी— महाअष्ट, महाष्ट हुँदै मष्टो भएको अड्कल गर्दछन्। मष्टोलाई निराकार बाल ब्रह्मचारी देवता मानिन्छ। पितृ स्वरूपमा वायु, प्रकृतिका स्वरूपमा लिङ्गो, ध्वजा, पताका, रक्षा सूचक हतियार आदि थापेर पूजा गरिन्छ। विक्रम संवत्को पाँचौँ शताब्दीतिर बझाङका राजा सैपाल थापाको समयमा मष्टोले राजकीय मान्यता पाएको थियो भन्ने गरिन्छ। तर लेख्य प्रमाण सन् १४५७ सुरती शाहले जारी गरेको एउटा अभिलेखमा पहिलो पल्ट मष्टो शब्दको उल्लेख गरेकाले यो नै सर्वाधिक प्राचीन मष्टो शब्द उल्लिखित अहिलेसम्मको प्रामाणिक अभिलेख मानिन्छ। खसहरूले मानी आएको मष्टो देवतालाई आर्य जातिले वेद, पुराणमा कतै उल्लेख नगरेकाले खसहरू आर्य नै हुन् भनेर मान्ने आधार नभएको एकथरी मत छ। अथर्ववेदमा खसहरूले मान्ने शिवलाई 'व्रात्य' भनेर हेपिएको र उनका अनुयायी खस जातिलाई 'व्रात्य जाति' भनेर खसालिएको छ। व्रात्य भनेको उपनयन वा यज्ञोपवीत संस्कार नगर्ने, अनार्य, वैदिक कृत्य आदि गर्ने अधिकार नभएको, जसको दश संस्कार हुँदैन भन्ने हो। आर्यका दुई समूहहरू बीचको वैमनस्यताले वा उनीहरूलाई चुनौती दिने आदिवासीहरूसँगको टकरावले यस्तो स्थिति आएको हुन सक्छ। वैष्णवहरूको वर्णाश्रम व्यवस्थालाई नमनेका हुनाले खसहरू र उनले मान्ने देवता शिवलाई व्रात्य भनेको हुनुपर्छ। आफूलाई ठुलो देखाउने र अरूलाई होच्याउने रूपमा आफूलाई देव खलक र अरूलाई राक्षस खलक भनेको हुनुपर्छ। राम्रो काम गर्ने आदर्शवान् व्यक्तिलाई देवता र अरूलाई दुःख दिनेलाई राक्षस भन्ने गरिन्छ। जरथुस्त्र धर्मग्रन्थको देवतालाई "असुर" र राक्षसलाई "दइव" भनिएको छ। ऋग्वेदमा असुर शब्दलाई १५ पल्ट नराम्रो र ९० पल्ट राम्रो अर्थमा प्रयोग गरिएको छ। असुर देवता र असुर सहरको बारेमा यसै आलेखमा अगाडि पनि उल्लेख गरिएको छ। मनुस्मृति तथा महाभारतमा उल्लेख गरिएका झल्ल, मल्ल, नट, करण, खस र द्रविडहरूलाई पाप योनिबाट जन्मिएका धर्मच्युत, व्रात्य जाति भनेर हेपेको पाइन्छ। यक्ष जातिलाई खस, चीन तथा मंगोल जातिलाई दरद र पिशाच, किरात जातिलाई किन्नर र द्रविडलाई बाहिक जाति भनेर हेपेको पाइन्छ। भारतको राजस्थानमा मष्टोलाई मामा देव, पहाडमा मामा ज्यू भन्दछन्। पिथौरागढमा चण्डक मष्टोको मन्दिर छ। बद्रीनाथमा मष्टोलाई घण्टाकर्ण देवता भनेर पूजा गर्छन्। दार्चुला-बैतडीतिर भूमिराज भनेर पूजा गर्छन्। लेखक तेज कार्कीले मष्टो प्रकृति पूजा (Shamanism) वा जडवाद (Animism) नै सर्वप्राचीन आध्यात्मिक चिन्तन भएको र मष्टो संस्कृति यही प्रकृति पूजक भएकाले यसको प्राचीनताको पुष्टि गर्न मिल्ने भाव व्यक्त गर्दछन्। मानव जातिले ३० हजार वर्षदेखि धर्म व्यापार र सामाजिक विभेदीकरण गर्न सिकेको नोआ हरारीको मत लेखक कार्कीले उल्लेख गरेका छन्। करिब ३२ हजार वर्ष पुरानो जर्मनीको स्टे डेल गुफामा भेटिएको सिंह मानव (पुरुष वा महिला) नै पहिलो धार्मिक चिह्न भएको (Harari, Yuval Noah (2015), Sapiens: A Brief History of Humankind, London: Vintage, P. 23/25) मान्दछन्। प्रकृति पूजाको प्रारम्भ साइबेरिया र मध्य एसियाबाट करिब २० हजार वर्ष पहिलेदेखि भएको र मष्टो परम्परा पनि प्रकृति पूजामा आधारित अत्यन्त प्राचीन परम्परा भएको सम्भवतः प्राग-ऐतिहासिक कालदेखि नै सुरु भएको मान्यता छ। मष्टोको प्रादुर्भाव खसहरूका पुर्खाहरूले बेबिलोनियामा शासन गरेको समयमा भएको मान्यता एकथरीको छ। विभिन्न मष्टोहरूका विभिन्न थानहरू हुन्छन्। खोला, किनार, रूखमुनि यिनका थान हुन्छन्। यिनीहरू डरलाग्दा, मानिसहरूलाई दुःख दिने, चाँडै रिसाउने स्वभावका हुन्छन्। ढँडार मष्टोका थान खोल/ढेल्यो र घाई, दुगे। बदु मष्टोका थान कुटासिली र छरिढुस्के, थापा मष्टोको थान घोडा, मौल्याल, गुम्देव, गाईगोठ्या आदि हुन्। नेपालमा मष्टो देवताको सुरुवात कहिले, कसरी र कहाँ भएको थियो भन्ने सन्दर्भमा विभिन्न अड्कल, आख्यान, किंवदन्तीहरू प्रचलित छन्। विभिन्न मत तथा अड्कल जे जस्ता भए तापनि बझाङ जिल्लाको ढँडार नै मष्टोको उत्पत्ति भएको सर्वाधिक प्राचीन स्थल हो भन्ने कुरामा अधिकांश मानिसहरूको सहमति छ। ढँडार मष्टोको एउटा मूल धामी हुन्छ। त्यो ढँडार मष्टोका धामीको मृत्यु भएपछि मात्र अर्को धामी हुने र भित्र पूजा गर्ने अर्को धामी बन्ने गर्दछन्। बाहिर बत्ती बाल्ने र अन्य काम गर्ने अन्य हुन्छन्। ढँडार मष्टोका हालसम्म ज्ञात पुजारीहरूमा परिङ्ग्या परिवारबाट १२ पुस्ता, सुवासकोटी नयरका १० पुस्ता, सुवेदी परिवारका १२ पुस्ता र जैसी परिवारका कुशु जैसीबाट सुरु भएर हाल १८औँ पुस्ताले मूल पुजारीको रूपमा काम गरिरहेका छन्। यसबाट यो मन्दिरमा मष्टो पूजाको परम्पराको प्राचीनताको अनुमान गर्न सकिन्छ। किंवदन्ती अनुसार मष्टो ढँडारमा जाँदा ढँडारका मानिसहरू खर्कमा गोठालो गएका थिए। गोठमा गाई-भैँसीका दूध राखेका भाँडाहरू खर्कबाट गोठमा आउँदा रित्तो हुने क्रम दिनदिनै हुन थालेपछि दिउँसो सबै मानिसहरू खर्क गएको बेला कसले दूध चोरेर खान्छ पत्ता लगाउनुपर्यो भन्ने हिसाबले लुकेर चियो गर्दा एउटा स्याल जस्तो जीव आएर दूध चोरेर खान लागेपछि सो जीवलाई देखेर कराउँदा उक्त जीव त्यही गोठमा आगो बालेको ठाउँबाट जमिन घस्रिएर करिब ४ किलोमिटर टाढाको पैंयादरो भन्ने ठाउँमा निस्कियो, त्यसलाई पैंयादरोको मष्टो भनिन्छ। उक्त जमिन घस्रिएर बनेको प्वाल अहिले पनि यथावत नै छ। अर्को यसै सँग मिल्दोजुल्दो किंवदन्ती पनि प्रचलित छ। कुश भट्ट नामक एकजना मानिस तीर्थाटन गर्न विभिन्न तीर्थमा जाँदा शंखधारमा एउटा शिला भेटेपछि उक्त शिलालाई आफूसँग लिएर हिँडे। राती सपनामा शिलाले आफू बेबिलोनिया तिरको देवता भएको र साइपाल हिमालको प्रस्रवण क्षेत्रमा बस्न चाहेको बताएछ। त्यसपछि उनले ढँडारमा माडौँ (थान) बनाएर शिला स्थापना गरे। त्यस ठाउँमा बँदेलले गोठालाको दही चोरेर खाने गरेपछि गोठालाले बँदेल समात्न खोज्दा सबै गोठाला बेहोस भएछन् र के भयो भनेर हेर्न आउने मान्छेहरू मध्ये जसराज भन्ने गोठालालाई कम्प छुटेछ र "म मरुत हुँ तिमी खसको कुलमुली हुँ। दैत्यको प्रहारबाट भवानीलाई बचाउन आएको हुँ, मेरो मन्दिर बनाउनुको सट्टा साधारण माडौँ बनाई त्यसको गाभिरमा खोपो राख्नु र मेरो गााधी सम्झेर पूज्नु, मेरो बहिनीको पनि सम्झना गर्नु" भन्ने किंवदन्ती प्रचलित छ। अर्को भनाइ अनुसार बझाङको चैनपुर नजिकैको सुवेडाका जोशी ब्राह्मण शंखधार र जालन्धरबाट ढुङ्गा (शिला) को रूपमा आएको बान्नी गएपछि ती ब्राह्मणले झोली बिसाएपछि भगवान् लुप्त भए, त्यो ठाउँ देउबाँझ (बाँझको रूख) को टोड्का (ढँड वा कसै-कसैले ढँडार पनि भन्दछन्) त्यही ढँडमा मष्टोको जन्म भयो। त्यहाँ बाँधिएकाले 'बान्नी मष्टो' भनियो। त्यहाँबाट विभिन्न ठाउँमा फैलिएकाले त्यसका भेदहरू भए। डोलने (हिँड्ने डुल्ने) भएकाले मष्टो-मष्टो भन्न थाले। १२ अङ्गालको मष्टो भन्ने पनि गरिन्छ, यसको मतलब मष्टोका १२ भेद भनेको होला। १२ ठाउँमा बसेकाले १२ उपमष्टो भनेको हो। मूल रूपमा मष्टोका दुई भेद छन्। मष्टो एउटै भए तापनि मष्टोले कहिले दूध र कहिले बलि खाने भएकाले एउटै मष्टोलाई दुधे मष्टो र दाह्रे मष्टो भनिएको हो। मूल थलोबाट मानिस अन्यत्र सरेर जाँदा र मष्टोका अनुयायीहरू विभिन्न ठाउँमा बढ्दै जाँदा विभिन्न ठाउँमा मष्टोका माडौँ स्थापना हुँदै त्यहीँका ठाउँ अनुसार मष्टोका भेदहरू बढ्दै १२ मष्टो, १८ मष्टो हुँदै मष्टोका १०० भन्दा बढी भेदहरू उल्लेख भएको पाइन्छ। जस्तै: बझाङको छबिस पाथीभेरा गाउँपालिकाको बान्नी भन्ने गाउँमा आएर बसे बान्नी मष्टो, मुगुको कावा मष्टो, बिजुली डाँडामा बसेको बिजुली मष्टो, ढँडारमा बसेको ढँडार मष्टो, थापा गाउँमा आएको थापा मष्टो। मानिसको बसाइँसराइ जहाँ-जहाँ भयो त्यहीँ मष्टो थान स्थापना गर्दै गए, कालान्तरमा जुन-जुन ठाउँमा मष्टो थान स्थापना भए त्यही ठाउँको नामबाट मष्टो नामाकरण हुँदै गए। यसरी एक सयभन्दा बढी ठाउँमा स्थापित मष्टोलाई त्यसका प्रकारको रूपमा भ्रमपूर्ण व्याख्या गरियो। दाह्रे मष्टो र दुधे मष्टो यसका केही उदाहरण निम्न छन्: १. कावा मष्टो २. कालो सिल्लो मष्टो ३. कफल्ना मष्टो ४. कैलाश मष्टो ५. कुड्या मष्टो ६. कालिकोट मष्टो ७. कालो मष्टो ८. कैली मष्टो ९. कुलदेव मष्टो १०. कालढुङ्गी मष्टो ११. कलसैन मष्टो १२. कमल मष्टो १३. कुँवरडा मष्टो १४. काफल मष्टो १५. कुर्मी मष्टो १६. कुमारी मष्टो १७. काँडा मष्टो १८. गदशितल मष्टो १९. चुनभ्यो मष्टो २०. चण्डक मष्टो (पिथौरागढ) २१. छल मष्टो २२. छन्ना मष्टो २३. जगन्नाथ मष्टो २४. टेडी मष्टो २५. तुसापानी मष्टो २६. ठिङ्गाल मष्टो २७. डडुवा मष्टो २८. दधिसिलट मष्टो २९. ढँडार मष्टो (आदिमष्टो) ३०. धाड्या मष्टो ३१. धुडीधुस्के मष्टो ३२. धोर मष्टो ३३. तेडी मष्टो ३४. तालिकोट्या मष्टो ३५. तमाचारी मष्टो ३६. थापा मष्टो ३७. दाह्रे मष्टो ३८. दुध्या (दुधे) मष्टो ३९. दुधेशिल्टो मष्टो ४०. दयाशिला मष्टो ४१. दुधेवराह मष्टो ४२. दाने मष्टो ४३. धुरङ्गो मष्टो ४४. धुपीरूख्खा मष्टो ४५. धौलीपुर्या मष्टो ४६. धौलापानी मष्टो ४७. धुसापानी मष्टो ४८. निगुनीको मष्टो ४९. पैंक मष्टो ५०. पन्त्या मष्टो ५१. पुआल्या मष्टो ५२. पञ्चालो मष्टो ५३. बुढ मष्टो ५४. विनायक मष्टो ५५. बिजुली डाँडा मष्टो ५६. बाबिरो मष्टो ५७. बबु मष्टो ५८. बाटपाल मष्टो ५९. बगारे मष्टो ६०. बडाकोटी ६१. बाजकोट्या मष्टो ६२. बाँसकोट्या मष्टो ६३. भ्वीन मष्टो ६४. भुवार मष्टो ६५. भैरो (भैख) मष्टो ६६. भुइँफुट्टो मष्टो ६७. भात्याखोला मष्टो ६८. भागे मष्टो ६९. भूमिराज (दार्चुला/बैतडी) मष्टो ७०. महावै मष्टो ७१. महादेउ मष्टो ७२. मशालो मष्टो ७३. मण्डली मष्टो ७४. मुण्डा मष्टो ७५. महारुद्र धौता मष्टो ७६. माटो मष्टो ७७. महामष्टो ७८. मामादेव (राजस्थान भारत) ७९. मामाजी (भारत) ८०. रुमाल मष्टो ८१. राउतकोट्या ८२. रामपाल मष्टो ८३. रागमचुला मष्टो ८४. राहदेउ मष्टो ८५. रुद्र मष्टो ८६. रुपा मष्टो ८७. लिगुनी मष्टो ८८. लताशिल्टो मष्टो ८९. लाकुडो मष्टो ९०. लखुरो मष्टो ९१. लडिपाल मष्टो ९२. लोहासुर मष्टो ९३. लामा-विष्णु मष्टो ९४. लड्या मष्टो ९५. लाटो धौ ९६. लाटोबाहुन मष्टो ९७. लहुरेवरा मष्टो ९८. लिउडी मष्टो ९९. लेखालि-डी मष्टो १००. वातिपाल मष्टो १०१. बान्नी मष्टो १०२. वाईफाला मष्टो १०३. वडावडा मष्टो १०४. शम्भु मष्टो १०५. साहिलाकम्ब मष्टो १०६. साइबारा मष्टो १०७. श्वेता मष्टो १०८. साइन मष्टो १०९. सुपारी पण्डित मष्टो ११०. सड्या मष्टो १११. सीम मष्टो ११२. सुनारगाउँ मष्टो ११३. सिमताडी मष्टो ११४. सुम्लेगुरो मष्टो ११५. सिद्ध मष्टो ११६. साकिदेउ मष्टो ११७. सर्किदेउ मष्टो ११८. हगुरो मष्टो ११९. हयाङ्ग्र मष्टो १२०. हिङ्गाल मष्टो १२१. ह्युना मष्टो १२२. क्षेत्रपाल मष्टो १२३. अछामी मष्टो १२४. आद्य मष्टो १२५. उखाडी (गुलाडी) मष्टो १२६. उब्या मष्टो १२७. खापर मष्टो १२८. खप्पा मष्टो १२९. खैरे मष्टो १३०. गुरो (गुरौ) मष्टो १३१. गुच्चु मष्टो १३२. गन्या मष्टो १३३. विजय मष्टो। मष्टोहरूको स्वभाव वा प्रकृति हेरेर यिनीहरूलाई गुणको आधारमा सत्त्व, रज र तम गुण युक्त हुने भनिन्छ। सत्त्वगुण भएका मष्टोहरूमा दुधे मष्टो, मण्डली मष्टो, लडे मष्टो आदि पर्दछन्। रजोगुण वा राजसी गुण भएका मष्टोहरूमा दाह्रे मष्टो, रुमाल मष्टो, तेडी मष्टो, खापर पर्दछन्। तमोगुण भएका मष्टोमा कालो मष्टो, रुपा मष्टो, कैलो मष्टो, मुण्ड मष्टो आदि पर्दछन्। ढँडार स्थित दाह्रे मष्टो ज्येष्ठ र श्रेष्ठ मानिन्छन्। थापा मष्टो विद्वान् मष्टो, बाबिरो मष्टोलाई कान्छो मष्टो मानिन्छ। गुरौ मष्टो र विजय मष्टोलाई भाइराजा मष्टो भनिन्छ। मष्टो उपासना गर्दा वैदिक विधि नअपनाएर धामीले प्राकृतिक विधि अपनाएर काँप्दै पूजा गर्ने गर्दछन्। मष्टो देवताको मूर्ति हुँदैन, यसमा स्वर्ग-नर्कको परिकल्पना गरिएको पाइँदैन। मष्टोको पूजा गर्दा साह्रो-गाह्रो पर्दा पनि भाकल गरी पूजा गर्ने पनि गरिन्छ। ढँडारमा मष्टो पूजा गर्दा विभिन्न जातजातिहरूको सहभागिता हुन्छ। दाह्रे मष्टोले मष्टो थानमा बलिको लागि लिएको बोका दाँतले छिनाल्ने गरिन्छ। बलि दिने सम्बन्धमा एउटा रोचक किंवदन्ती प्रचलित छ। एकपल्ट बझाङी राजाले बलि दिनुपर्यो भन्दा माघको महिनामा बलि दिन मिल्दैन भनेपछि राजाले नमानी बलि दिन हठ गरेछन्। त्यसपछि राजाले निकै जिद्दी गरेपछि मष्टो चलेछ र राजाले बोकालाई गाईको बाच्छो बनाइदिएछन्। मष्टोले त्यो देखेर त्यसलाई बाघ बनाइदिए, मष्टोले बाघ बनाएको देखेर राजाले सर्प बनाइदियो। राजाले सर्प बनाएपछि मष्टोले गरुड बनाइदिए। राजाले बोकाको घाँटीमा फलामको पाता बाँधिदियो र मष्टोले पातासहित बोकाको घाँटी दाँतले छिनालिदिए। त्यो देखेर राजा रिसायो। अहिले पनि मष्टो चल्यो भने मष्टोले "तँ जिउँदो होइज म पन्छी होइजुँ, तँ खैर होइज म बाघ होइजुँ" भनी बोल्दछन्। ढँडारमा शनिबार र मंगलबार बलि (दाँतले) दिइन्छ। अरू बार दूध, चामलले पूजा गरिन्छ। पर्वको समयमा चैते दशैँमा बलि हुन्छ। जन्माष्टमीमा बलि हुँदैन। जुठो, सुतक परेको बेला मष्टोको पूजा हुँदैन। ढँडारमा नयाँ धामी निस्किए भने देउता चढेपछि दाँतले बोका छिनाल्नुपर्ने र धामी प्रमाणित भएपछि मष्टो देवताको अवतार भयो भनी ताल्कोटी राजाले धरी, पगडी, कानमा मुन्द्रा, बाला प्रदान गर्दछन्। त्यसपछि कुँवर जाति अनि ब्राह्मण जाति हुँदै अन्य हिलो पूजामा सहभागी हुन्छन्। मष्टो धामीमा मात्र आउँदछ। जुनसुकै नयाँ बाली भए पनि दाह्रे मष्टोलाई चढाएर मात्र आफूले खाने चलन छ। धामीले जाँड-रक्सी खानु हुँदैन। बलि दिने बेलामा धामीको स्वरूप डरलाग्दो हुन्थ्यो। त्यस्तो डरलाग्दो स्वरूप देखेर मानिसहरू डराउने भएकाले कपडाले छेकेर बलि दिने गरिन्थ्यो। जति बोका बलिका लागि ल्याइन्थ्यो ती सबैलाई दाँतले छिनालेर बलि दिने गरिन्थ्यो। बझाङी राजा गजराजले धामीको जाँच गर्न बोकाको घाँटीमा फलामको पाता बाँधेर बलि दिन ल्याएको र सो बोकालाई पातासहित दाँतले छिनालेको भनाइ छ। मष्टो भनेको एउटा मात्र हुन्छ। दाह्रे मष्टो र दुधे मष्टो भनेको एउटै मष्टोका राजसी र कार्यकारी वा रज र सत्त्व स्वरूप हो भन्ने मत पनि छ। दाह्रे र दुधे मष्टो भनेको एउटै हो मष्टोको संयुक्त रूप हो। आइतबार र बुधबार दुधे मष्टोको पूजा गरिन्छ दाह्रे मष्टो पनि सँगै हुन्छ। जुम्लाका मानिसहरू प्रायः ढँडारमा पूजा गरेपछि त्यहाँबाट बक्साएर अन्यत्र जान्छन्। ढँडार नै मष्टोको मूल थलो भएको र यसरी विभिन्न ठाउँमा विभिन्न नामका मष्टोहरू मूल स्थानबाट छुट्टिएर जुन-जुन स्थानमा गएर बसे त्यसै ठाउँको नामबाट ती ती मष्टोको नामबाट चिनिन थाले। खस जातिको पुरापूर्वकालमा १२ वटा समूह रहेको र हरेक समूहले छुट्टाछुट्टै मष्टो पूजा उपासना गर्ने भएकाले 'बाह्र भाइ मष्टो' भनिएको धेरैको अनुमान छ। बाह्र भाइ मष्टो को हुन् भन्ने बारेमा मतैक्यता छैन। कहीँ-कहीँ मष्टोलाई शिवको अंश मानेर पूजा गर्ने चलन पनि छ। कतिपयले मष्टोलाई इन्द्रपुत्र भन्ने विश्वास गर्दछन्। मष्टोका ५२ वीर र १६ मर्सानीहरू सुरक्षार्थ रहन्छन् भन्ने मान्यता पनि पाइन्छ। मष्टो सम्बन्धी विभिन्न किंवदन्तीहरू प्रचलित छन्। एउटा किंवदन्ती अनुसार एकपटक मन्दिरको नजिकै बसेर वेदपाठ गरिरहेका धवलपुरलाई असुरले टुक्रा-टुक्रा बनाएर मार्ने र उनले पढिरहेको वेदलाई जलाउने योजना बनाए। असुरको यो योजना थाहा पाएपछि मष्टोको भान्जा बान्नी मष्टोले वेदलाई मष्टोमाण्डौ नजिकै शिलामा परिणत गरिदिए र असुरको हातबाट मामा धवलपुरको ज्यान बचाए। त्यसै बेलादेखि मष्टो उपासकले भान्जालाई झोलीको देवता मान्ने गरेका हुन्। झोलीको देवतालाई मष्टोसँगै शिला स्थापना गरेर भान्जाको पनि पूजा गर्ने परम्परा चलेको हो भन्ने गरिन्छ। मष्टो सम्बन्धी एउटा आख्यान अनुसार देवासुर संग्राममा असुरहरूले पराजय भोगेपछि देवताहरूसँग शरण माग्न बाध्य भए तापनि उनीहरूको मनमा द्वेष बाँकी थियो। पछि असुर संगठित भए र उपद्रो गर्न थाले। आफूलाई पतन गराउने कारकको रूपमा दुर्गा भवानीलाई मानेर उनको अपहरण गरे। केहीले उनीमाथि बलात्कारको प्रयास समेत गरे। देवताहरूले अनेकौँ प्रयत्न गर्दा पनि देवी दुर्गालाई बन्दी बनाएको ठाउँ पत्ता लगाउन नसकेर भगवान् शंकरको आराधना गरे। त्यसपछि शंकरका शक्तिशाली गण देवता मष्टोको नेतृत्वमा युद्ध दलले दुर्गा र उनका बहिनीहरूलाई मुक्त गरी असुरहरूलाई छिन्नभिन्न पारेका हुनाले नवदुर्गाले मष्टोलाई भाइ भनी मानेकाले दुर्गा पूजा हुँदा मष्टोको आह्वान गरिनुका साथै मष्टोले देवभाग पाउने भए। मष्टोलाई दुष्टको दमन गर्ने, खराब विचारले अभिप्रेरित स्वार्थी र दुष्टात्मालाई दमन गर्ने र निमुखा र सत्यको पक्षमा कल्याणकारी देवताको रूपमा खसहरूको रक्षा गर्ने महान् देवताको रूपमा आदिकालदेखि पूजा, भक्ति र श्रद्धा गर्ने देवताको रूपमा खसहरूले पुज्दै आएका छन्। उपेक्षित, अपमानित, दुःखी मानिसहरूलाई बढ्ता स्नेह गर्ने भएकाले मष्टो समस्त खसहरूको लोकप्रिय देवता हुन पुगेका छन्। अर्को किंवदन्ती अनुसार सान्नी राज्यका राजा जसलाई सन्याल राजा पनि भनिन्छ। बाइसे राज्य कालको समयमा हालको कालिकोट जिल्लाको मेहेलमुडी गा.वि.स. मा सान्नी राज्यको राजधानी थियो। उनको राज्यमा सान खड्का र संसारे खड्का नाम गरेका २ भाइ थिए। ती दुई भाइमध्ये सानलाई दाह्रे मष्टो चढ्यो। दाह्रे मष्टो चढेपछि सीधासाधा सानले अस्वाभाविक कार्य गरेको देखेर सन्याल राजाले देउता चढ्यो कि दानव चढ्यो भनेर जाँच गर्ने विचार गर्दा राजा र देवता बीच लडाइँ भयो। राजाका दुई भाइ भान्जा र कुवेर थिए। भान्जाले केही नगरे पनि कुवेरले धनुकाँडले धामीलाई लखेट्न थाल्यो। दाह्रे मष्टो चढेका धामी त्यहाँबाट भागेर एउटा ठुलो रूखमा चढे र त्यहाँ पनि उसलाई लखेट्दै राजा आएकाले नजिकैको चुरी खोलामा फाल हालेर वेपत्ता भए। राजा पनि धामी मरे भन्ने ठानेर घर फर्कियो। धामी मरेको हल्ला फैलिएपछि उनकी पत्नी सती जाने तयारी गरिरहेको बेला धामी सर्पको कडेली (लगाम) बाघको घोडा चढेर दाह्रे मष्टो चढेका धामी आए। राजाले त्यो कुरा थाहा पाएर उनलाई मार्नको लागि ४०० भेडा राखेको खोरमा थुनेर सबै झ्याल ढोका बन्द गरिदिए। मष्टो चढेका धामीले ४०० भेडा मध्ये एउटा खसी बाहेक सबैलाई दाँतले छिनालेर मारे। त्यो देखेर भेडी गोठालो अत्यन्त दुःखी भयो। मष्टोले उसलाई सान्त्वना दिँदै उसलाई धनधान्यले पूर्ण गरी उसको सन्तान कहिल्यै नमासिने र कहिल्यै वृद्धि पनि नहुने वरदान दिए। उनका कयौँ पुस्ता बितिसक्दा पनि अहिलेसम्म उनका सन्तानहरूमा एकजना मात्र जन्मने कुराको निरन्तरता अहिलेसम्म पनि पाइन्छ। सन्याल राजाले मष्टोमाथि गरेको दुर्व्यवहारले उनीहरूका घरमा सधैँ कलह अशान्ति र हैरानी भइरहने भएकाले त्यहाँबाट अन्यत्र सर्ने विचारले जाने बेला लाकुर देवतासँग बिदा हुन गए। लाकुर देवता मष्टोका भान्जाले सम्झाए र दाह्रे मष्टोको सेवा गर्ने सल्लाह दिए। सन्याल राजाले दाह्रे मष्टोको मन्दिर निर्माण गरे। आफ्नो सम्पूर्ण सम्पत्ति, राज्य दाह्रे मष्टोलाई चढाउने प्रस्ताव गरे। दाह्रे मष्टो चढेका धामीहरूसँग यस्तो प्रस्ताव राखेपछि मष्टोले "सबै राज्य सम्पत्ति चढाएपछि तँ कहाँको राजा हुन्छस्? मलाई सबै सम्पत्ति चाहिँदैन, ३ भाग लगाएर २ भाग तिम्रा भाइले बाँड्नु, १ भाग मलाई दिनु" भनेको र राजाले सोही अनुसार गरेकाले दाह्रे मष्टोले सन्यालको एक अंश खाएकाले सन्याललाई भाइपीठ्या भनेर मष्टो चढेको बेला भन्ने गरिन्छ। डा. जगमान गुरुङले जुम्ला सिंजा पाण्डुसेरामा प्रचलित १२ मष्टोका नाम उल्लेख गरेका छन्। १. आदिमष्टो २. कालो मष्टो ३. बबुरो मष्टो ४. रुमाल मष्टो ५. दुधे मष्टो ६. दाह्रे मष्टो ७. मण्डली मष्टो ८. बान्नी मष्टो ९. थापा मष्टो १०. ढँडार मष्टो ११. कावा मष्टो १२. खापर मष्टो। हुम्लाको सोरुदरामा रहेको गुरौ मष्टोलाई कसै-कसैले देवताको रूपमा मान्दैनन्। यो अत्यन्त दुष्ट स्वभावको राक्षसी व्यवहार देखाउने खालको हुने बताइएको छ। मष्टो कुन देवता हुन् भन्ने बारेमा फरक-फरक मत पाइन्छ। कसैले वायुको रूपमा, कुनै अवस्थामा साधुको रूपमा, कुनै-कुनै अवस्थामा गरुडको रूपमा र कहीँ-कहीँ बिरालोको रूपमा मष्टो रूपान्तरित हुन्छन् भन्ने मत पाइन्छ। मष्टोलाई कुल देवता र इष्ट देवताको रूपमा पनि लिने गरिन्छ। कतिपय मानिसहरूले वराह मष्टो भन्ने गरेपछि जुम्लाका १२ भाइ मष्टोको अपभ्रंश रूप र जुम्लाको कालिकोट दरामा ढँडार मष्टोलाई पाण्डवको अवतार, खापर मष्टोलाई इन्द्रको छोरा भन्ने कुरा बाहुन र ठकुरीले हालेको कथामा मात्र पाइन्छ भन्ने कुरा डा. जगमान गुरुङले मान्दछन्। प्युठानमा बसोबास गर्ने खप्तडी बस्नेतहरू कैलासिनी, विन्ध्यवासिनी आदि नौ बहिनीको दिवाली पूजा गर्ने गर्दछन्। कौशिक गोत्रीय बस्नेतहरूका कुलदेवता कसरी फरक-फरक? कौशिक गोत्रीय खप्तडी बस्नेतहरूका कुल देवता दाह्रे मष्टो हुन्। पश्चिम नेपालका सबै बस्नेतहरू दाह्रे मष्टोलाई कुल देवताको रूपमा मान्दछन्। पूर्वतिरबाट बसाइँ सरेर आएका बस्नेतहरू बाहेक सम्पूर्ण बस्नेत लगायत अरू धेरै थरहरूका कुल देवता पनि दाह्रे मष्टो नै हुन्। तर पूर्व नेपालका विभिन्न ठाउँमा बस्ने कौशिक गोत्रीय खप्तडी बस्नेतहरू खापर मष्टोलाई आफ्नो कुल देवता मान्दछन्। प्युठानमा बसोबास गर्ने खप्तडी बस्नेतहरू कैलासिनी, विन्ध्यवासिनी आदि नौ बहिनीको दिवाली पूजा गर्ने गर्दछन्। एउटै थर गोत्रका मानिसहरू बीच कुल देवता किन फरक भन्ने प्रश्न उब्जनु स्वाभाविकै हो। यो कसरी यस्तो हुन गयो, त्यस बारेमा सोधखोज र निरुपण नहुञ्जेल अलग कुल देवता मान्ने बस्नेतहरू बीच कुल देवताको बारेमा केही भ्रमहरू रहिरहने भएकाले तथ्य के हो भन्ने बारेमा उजागर गर्न आवश्यक छ। प्राचीन कालमा बाह्र भाइ मष्टोहरू ढँडारमा बसेको बेला उनीहरू बीचमा वैमनस्यता उत्पन्न भएर ठुलो द्वन्द्वको स्थिति आयो। भरसक सबैलाई मिलाएर लैजाने जेठो र सर्वाधिक शक्तिशाली दाह्रे मष्टो (जसलाई गादी मष्टो पनि भन्दछन्), उनी सबैका नायक गद्दीमा राज गर्ने भएकाले र सबैका अगुवा नायक भएकाले द्वन्द्व हुन नदिन निरन्तर प्रयत्नशील हुन्थे। निरन्तरको मनमुटाव र द्वन्द्वको स्थिति कायमै रहेको बेला एक दिन सबै भाइ खप्तडको जङ्गलमा मालिङ्गो काट्न जाने सल्लाह भयो। त्यहाँ खानको लागि रुमालमा बाबर (रोटी), ठेकीमा दही, दूध, मालिङ्गो काट्ने हतियार समेत लिएर उनीहरू गए। मालिङ्गो काटिरहेको बेला अकस्मात उनीहरूमा झगडा पर्न गयो। सबैलाई सम्झाई-बुझाई गरी शान्त गर्न जेठो दाह्रे मष्टोले अनेक प्रयत्न गर्दा पनि अरू भाइले नमानेको र लडाइँले झन्-झन् उग्र रूप लिएकाले दाह्रे मष्टो रिसाएर दाह्रा किट्दै भर्खरै काटेको मालिङ्गोको ठुटाले हानेर एकजनाको खप्पर फुटाइदिए। त्यसरी खप्पर फुटाई माग्ने खापर/खापर मष्टो भनियो। अर्कोलाई कालो शिलाले हिर्काएर भगाएको, उनी उक्त शिला टिपेर भागे र अछामको विनायककोठ गए र विनायककोठे राजासँग द्वन्द्व भएपछि त्यहाँबाट भागेर विनायक भन्ने स्थानमा गएर आफूसँग भाग्दा लिएको कालो शिला त्यहीँ स्थापना गरे र कालो सिल्लो मष्टोको रूपमा स्थापित भयो। रोटी बोकेर ल्याएको रुमाल टिपेर भाग्ने खिड्कीसैनीमा गएर बस्यो र रुमाल मष्टोको नामले स्थापित भयो। अर्को भाइले सँगै ल्याएका बाबर टिपेर त्यहाँबाट भागेर जुम्लाको बाबिरो गाउँमा गएर बसेकाले बाबिरो मष्टोको रूपमा चिनियो। दूध-दही बोक्ने अलि सोझो अरूसँग झगडा नगर्ने सोझो भाइलाई आफूसँगै बस्न आग्रह गरेको र आफू पछिको स्थान ग्रहण गर्न सक्ने छुट दिएकाले उनी दुधे मष्टो कहलाएर उनलाई आफू पछि दूधको धार दिने व्यवस्था मिलाए। सबै भाइको आ-आफ्नो स्थान पाएकाले उनलाई ढल्लुको भाग दिए र त्यहाँ उनको धाम स्थापित गरे। उता खप्पर फुटाई मागेको खप्पर/खापर मष्टो त्यहाँबाट भागेर डोटी क्षेत्रतिर गए। त्यस समयमा डोटी, बोगटान, दार्चुला, कत्युरी राजवंशको अधीनमा थियो। कत्युरी राजवंशको स्थापना सातौँ शताब्दी आसपासमा सम्राट बासुदेवले गरेका थिए। यो राज्यको पहिलो राजधानी जोशी मठ र दोस्रो राजधानी बैजनाथ रणचुलाकोट थियो। यिनीहरू भगवान् केदारनाथ (शिव) भगवान्का भक्त थिए। यिनीहरू स्वामी कार्तिकेयको पूजा गर्दथे र कार्तिकेयबाट कार्तिकेयपुर र कार्तिकेयपुरका शासक भएकाले उनीहरूको वंशलाई कत्युरी वंश भनिएको मान्ने गरिन्छ। वैशाख शुक्ल मोहनी एकादशीको दिन कार्तिकेयलाई कार्तिकेयपुरबाट डोटीमा ल्याएपछि मोहनी एकादशीबाट उनलाई मोहण्याल नामले ख्याति प्राप्त भयो। यिनै मोहण्याल कत्युरीहरूका कुल देवता हुन्। कार्तिकेयको जन्मेको बारेमा पनि रोचक किंवदन्ती छ। भगवान् केदारनाथ (शिव) का दुई पुत्रहरूको जन्म भयो, गणेश र कार्तिकेय। दुई पुत्रको जन्म भएपछि केदारनाथ अत्यन्त खुसी भए र उनले आफ्ना दुई पुत्रको बारेमा जान्न जोशीमठका ज्योतिषीलाई देखाउँदा ज्योतिषीले गणेश महान् विद्वान्, बुद्धिमान् हुने र कार्तिकेय महान् बलशाली हुने, ती कार्तिकेय मूल नक्षत्रमा जन्मेको र केदारनाथलाई अनिष्ट हुने कुरा बताएपछि मोहनीलाललाई केदारनाथले तामाको ढोलभित्र हाली मन्दाकिनी नदीमा बगाइदिए। यो नदी हिमालयको चोरबारी दहबाट उत्पन्न भएर सोन प्रयागमा कालीगङ्गासँग र बद्रीनाथबाट आउने अलकनन्दा नदीसँग रुद्र प्रयागमा मिल्दछ। नदीमा अलि तल गोविन्दघाट नामक स्थानमा माझीले जाल हानिरहेको बेला अयोध्याका राजा घोडामा सवार भएर त्यहाँ पुगे। मन्दाकिनी नदीमा मोहण्याललाई हालेर बगाएको तामाको ढोल बग्दै त्यहाँ आएको देखेर त्यो के चिज हो भन्ने कौतूहलता लागेर राजाले माझीलाई जाल हान्न लगाएर त्यसलाई नदी किनारमा ल्याउन लगाए। माझीले त्यो ढोललाई जालमा पारेर नदी किनारमा ल्यायो। अलि पर नदी किनारमा लिएर राजाले त्यो ढोल खोलेर हेर्दा त्यसबाट बालक मोहण्याल निस्किए। उक्त ठाउँ त्यसै गोडियाको नामबाट गोविन्दघाटले प्रसिद्ध भयो। मोहण्याललाई विश्व भित्रका सन्ततिले उत्सवपूर्वक पूजाआजा गरे। त्यसबेला तामाको ढोल बजाउने कश्यप गोत्रीय ऐरी मोहण्यालको ढोली भयो। उता भागेर डोटी पुगेको खापरे/खापर मष्टोले मोहण्यालको माटो (राज्य) जहाँ "१२ बोघानका राजा मोहण्याल हुन्" भन्ने गरिन्छ, त्यहाँ गएर बलजफ्ती उनको पहाडी भू-भागमा कब्जा जमाएर आफ्नो हैकम जमाउन खोज्ने र त्यहाँका मानिसलाई दुःख दिएर आतंक मच्चाएको थियो। त्यस्तो स्थितिमा त्यही देवभूमिको देउताहरूले बडातोडो देउतालाई पुकारा गर्दै भने: "जान दैत्य बडातोडो मालथली जान। मोहण्याल दैत्यको दलु कत्युर लान..." देउताले यस्तो पुकार गरेकाले बडातोडो देउता मोहण्याललाई लिन मालथली हुँदै कत्युर गयो। "गयो दैत्य बडातोडो, बतासैको स्वर। आयो दलु मोहण्यालको बादलकी ढिक।" मोहण्यालको आगमन पछि मोहण्यालले आफ्नो गणलाई निर्देशन दिँदै भने: "मिल्ला छौ त खापरे, हामुसित मिल। नै त मिल्ला खापरेकी लाँत तेरी ठीक। केदारका दाहिने तिर तुड्या तुड्या पानी। नै त मिल्ला खापरेकी समाई ल्याए रानी। केदारैका गाथ मुनि थुम थुम केला। नै त मिल्ला खापरेका समाई ल्याए चेला।" त्यसपछि खापरसँग युद्ध हुन्छ। युद्धमा ५२ र ५३ दल भएका देवी देउताहरूले मोहण्याललाई सहयोग गरे। घमासान युद्ध भएपछि खापरको नराम्रोसँग हार भयो। खापरलाई नराम्रोसँग कुटी सेती नदी कटाएर लखेटे। युद्धमा मोहण्यालको खापरले दाँत भाँचिदिएको र मोहण्यालले खापरको बायाँ खुट्टा भाँचिदिएको थियो र आफ्नो भूमिमा उसले पूजा गर्न नपाउने गरिदिएकाले अहिले पनि खापर मष्टोका धामी एक खुट्टाले लङ्गडो भएर काँप्ने गर्दछन्। त्यसपछि खापरसँग युद्ध हुन्छ। युद्धमा ५२ र ५३ दल भएका देवी-देवताहरूले माहेन्याललाई सहयोग गरे। घमासान युद्ध भएपछि खापरको नराम्रोसँग हार भयो। खापरलाई नराम्रोसँग कुटी सेती नदी कटाएर लखेटे। युद्धमा माहेन्यालले खापरको दाँत भाँचिदिएको र माहेन्यालले खापरको बायाँ खुट्टा भाँचिदिएको थियो। आफ्नो भूमिमा उसले पूजा गर्न नपाउने गरिदिएकाले अहिले पनि खापर मष्टका धामीहरू खापर मष्टको पूजा गर्दा जमिनभन्दा अलि अग्लो अठारो (टाँड) बनाएर, त्यसलाई माहेन्यालले नदेखास् भनेर स्याउलाले बारेर खापरको पूजा गर्छन्। माहेन्यालले बायाँ खुट्टा भाँचेकाले खापरका धामीले काँप्दा बायाँ खुट्टा भाँचिएको आफ्नो देवताको नक्कल गरेर बायाँ खुट्टा उठाएर दायाँ खुट्टाले मात्र खोच्याउँदै काँप्ने र नाच्ने गर्छन्। अरू समयमा समेत घरको देवता राखेको कोठाको झ्यालमा माहेन्यालले नदेखास् भनेर स्याउला राख्ने चलन छ। खापर मष्ट पुज्ने खप्तडी बस्नेतहरूले आफूलाई प्रकृति पूजक हौं भन्ने गरे तापनि उनीहरूले खापर मष्टको बायाँ खुट्टा भाँचिएको मूर्तिको पूजा गर्ने गर्दछन्। यस्तो सयौं वर्षदेखि परम्परागत रूपमा पूजिँदै आएको घुँडाबाट बायाँ खुट्टा भाँचिएको, जनै लगाएको र कुर्सीजस्तो आसनमा बसेको खापर मष्टको धातुको प्राचीन मूर्ति कैलालीको मडकाैनाका बस्नेत परिवारमा सुरक्षित रूपमा पूजा स्थलमा रहेको र पूजिँदै आएको पाइन्छ। यस्तो मूर्ति राखिएको भँडारको झ्यालमा पूजा गर्दा माहेन्यालले नदेखुन् भनेर उनलाई छेक्नका लागि सधैं स्याउला राखिन्छ। खापर मष्टको पूजा गर्दा बोकाको बलि पनि भुईँमा दिन नमिल्ने भएकाले घरको माथि अठारोमा वा बाहिर पुज्दा जमिनमाथि बनाएको अग्लो टाँडमा दिने गरिन्छ। खापर मष्टको पूजा ३ वर्षमा १ पटक (वनदेवी कालिकासँगै राखेर) गर्ने गरिन्छ। यसरी माहेन्यालसँग नराम्रोसँग पराजित भएपछि आफ्नो बस्ने ठाउँ कतै नभएको र पश्चिम, उत्तर, दक्षिण र पूर्वतिर समेत माहेन्यालको राज्य भएकाले त्यहाँबाट खापर मष्ट र त्यसका अनुयायी तथा खापर मष्टका पूजक बस्नेतहरू देवतासहित भागेर पूर्वतिर लागे। युद्धमा धेरै धनजनको क्षति भएको र नजिकै बस्दा १२ बथानका राजा समेत रहेको माहेन्यालको सधैं भय रहिरहने भएकाले डोटी क्षेत्रबाट भागेर गएकाहरू र तिनका सन्तानहरू गण्डकी क्षेत्रको लमजुङ आसपासमा बसोबास गरे। पछि द्रव्य शाह लिगलिगकोटको दौडमा विजयी भएर राजा भएको समयमा द्रव्य शाहका नजिकका सहयोगीको रूपमा उनीहरू त्यहाँ रहे र पछि गोरखा दरबारका विश्वासपात्र बने। सहयोगीमध्येका भूपालमानका सन्तान गोरखा मै बसे र वंशराजका छोराका सन्तान पूर्वतिर हान्निए। तिनीहरू त्रिशूली पार गरेर नुवाकोट र नुवाकोटपछि दोलखातिर गए। त्यहाँका मानिसहरूसँग मिल्न नसकेपछि स्थानीय मानिसहरूले खप्तडी बस्नेतहरूलाई लखेटे। त्यहाँबाट भागेर वेताली गए। वेतालीका मानिसले पनि त्यहाँबाट लखेटेर लिखु खोलामा सुनुवारहरूको किपट भएको जमिनमा गए। पछि सुनुवारले त्यहाँबाट पनि धपाउन खोज्दा सुनुवारलाई चलनचल्तीको तिरो तिरेर बसे। केही समयपछि उनीहरूका सन्तानमध्ये एक भाइ सोलु र अर्को भाइ भोजपुरतिर गए। भोजपुरका शक्तिशाली राईले आफ्नी छोरीमाथि आँखा लगाएकाले राईबाट छोरी जोगाउन भागेर दूधकोशीको पश्चिम किनारातिर बसाईँ सरेको र यसरी गण्डकी क्षेत्रबाट पूर्वी नेपालका विभिन्न क्षेत्रमा खापर मष्टका अनुयायी बस्नेतहरू फैलिएर बसेको हुँदा उनीहरूसँगै खापर मष्ट उनीहरू बसोबास गरेको क्षेत्रतिर कुलदेवताको रूपमा मानिँदै आएको हो। पूर्वबाट बसाईँ सरेर पुनः पश्चिम तर्फ गएका अत्यन्तै नगण्य संख्याका बस्नेतहरूबाहेक पश्चिम तर्फ अनादिकालदेखि बस्दै आएका बस्नेतहरूले खापर मष्ट मान्ने गरेको पाइँदैन। १२ भाइ मष्टहरू धडाँर छोडेर विभिन्न ठाउँमा गएपछि दाह्रे मष्ट धडाँरमा भइरहे र उनका अनुयायी खप्तडी बस्नेतहरूको एउटा ठूलो समूह पनि त्यही रह्यो। लामो समयपछि जनसंख्या वृद्धि हुँदै जाँदा दाह्रे मष्टको एउटा पीठको रूपमा मुगुको खत्याड डाँडा कौवामा दाह्रे मष्टको माडौं स्थापना गरी कावा मष्टका रूपमा स्थापित भए। कौवाबाट कफल्लामा मष्ट सरेर आएको बताइन्छ। कफल्लामा मष्टको ख्याति चारैतिर फैलिएपछि ठूलो संख्यामा मानिसहरू आउने र ठूलो संख्यामा बलि चढ्ने गर्दा, बलि चलेको बेला धामीको श्रीमतीले दाह्रे मष्टप्रति नकारात्मक र दुर्वच्य बचन बोलेकाले त्यसको परिणाम स्वरूप उनको मृत्यु भयो। त्यसपछि दाह्रे मष्ट त्यहाँबाट बिजुली डाँडामा सरेर गएको र दार्नागाउँ र सिमपाखा गाउँलाई श्राप दिएको कारण अहिले पनि ती गाउँहरू उजाड भएर बस्ती हराएर गएको पाइन्छ। बिजुली डाँडामा केही समय बसेपछि त्यहाँबाट जाजरकोटको पैंकमा दाह्रे मष्ट सरेर गए। हाल बिजुली डाँडामा दुधे मष्ट मात्र रहेका र दाह्रे मष्ट पैंकमा सरेका छन्। यसरी विभिन्न कालखण्डमा विभिन्न स्थानमा मानिसहरूको बसाईँसराइसँगै उनीहरूले मान्ने कुलदेवता सँगसँगै जाने हुनाले दाह्रे मष्ट मान्ने कौशिक गोत्रीय खप्तडी बस्नेतहरू विभिन्न ठाउँमा बसाईँ सरेर गएको र त्यहाँ दाह्रे मष्टका मन्दिर स्थापित हुँदै गएको पाइन्छ। बझाङको धडाँरबाट दाह्रे मष्ट मान्ने कौशिक गोत्रीय खप्तडी बस्नेतहरू मुगु, जुम्ला, दैलेख, जाजरकोट, सल्यान, रुकुम, रोल्पा जस्ता पहाडी जिल्लातिर बसाईँसराइ गर्दै मष्ट माडौं स्थापित गर्दै गए। पछि तराईको राज्य एकीकरण र औलो उन्मूलनपछि सल्यान, रोल्पा, रुकुम, प्युठान आदि जिल्लाबाट दाङ; जुम्ला, कालिकोट, मुगु, दैलेख जस्ता पहाडी क्षेत्रबाट सुर्खेत, बाँके, बर्दिया र अछाम, डोटी, बझाङ, बाजुरा आदि स्थानबाट कैलाली कञ्चनपुर जस्ता तराईका जिल्लामा बसाईँसराइ गरेर आएका खप्तडी बस्नेतहरूले तत् तत् स्थानमा आफ्ना कुलदेवताको स्थापना गर्दै गए। यसरी विभिन्न ठाउँ जहाँ मष्टको स्थापना भयो, त्यसै ठाउँको नामबाट मष्टको नाम पनि रहन गयो। जस्तै: धडाँर गाउँबाट धडाँर मष्ट, बडु गाउँबाट बडु मष्ट, थार्प गाउँबाट थार्प मष्ट, बिजुली डाँडाबाट बिजुली मष्ट, कौवा गाउँबाट कावा मष्ट, पैंक गाउँबाट पैंक मष्ट आदि। १२ मष्ट जहाँ-जहाँ उत्पन्न भए, त्यहाँका मूल थलोहरूमा शिवलिङ्गहरू स्वतः उत्पन्न भएको मानिन्छ। यो कतै विभिन्न नामका शिलाको रूपमा र कतै शिवलिङ्गको स्वरूपमा प्रकट भए। मष्टलाई कतै शिवको सहयोगी र कतै शिवको अंशको रूपमा उल्लेख गरिएको छ। मष्टको माडौं तथा घरमा मष्ट स्थापना गरेको स्थानमा शिवलाई सिद्ध वा महादेवको रूपमा ध्वजा टाँग्ने गरिएको हुन्छ। सिद्ध (शिव) सात्त्विक देवता भएकाले बलि नचढाउने र उनलाई पानीको धार दिने गरिन्छ। त्यस्तै दाह्रे मष्टसँगै दुधे मष्टलाई पनि स्थापना गर्ने गरेको स्थिति भनेको मष्ट मूल रूपमा दाह्रे र दुधे मात्र हुन्छन्। दाह्रे र दुधे भनेको एउटै मष्टको दुई रूप सात्त्विक र राजसी भन्ने मान्यता पनि छ। त्यसैकारण दुधे मष्टलाई दूधको धार र दाह्रे मष्टलाई रक्त बलि दिने गरिन्छ। एउटै गुवारा (गुठी/पूजास्थल) भित्र ३ प्रकारका धार (पानी, दूध र रगत) चढाउने कार्य दार्शनिक हिसाबले मानिसले जीवन र जगत्को व्याख्या सृष्टि, स्थिति र संहारको सचेतनात्मक सांकेतिक अभिव्यक्तिको सूक्ष्म चेतनाको स्वरूपको अर्थमा लिन सकिन्छ। • जल (पानी): सृष्टिको प्रतीक हो। जीवनको प्रारम्भ वा सृष्टिको सांकेतिक अभिव्यक्ति हो। • दूध: स्थितिको प्रतीक हो। अर्थात् मानवीय कर्मको सांकेतिक अभिव्यक्ति हो। मानिस बाँच्नका लागि, पुरुषार्थका लागि र जीवनको सार्थकताका लागि कर्म गर्नुपर्दछ। कर्मबाट नै दूध, अन्न, फलफूल जस्ता कुराहरू प्राप्त हुन्छन्। • रगत (बलि): संहारको प्रतीक हो। संसारमा जन्मेपछि संहार वा अन्त्य अनिवार्य छ। यसबाट मुक्ति पाउन वा यसलाई छल्न सकिँदैन भन्ने कुराको सांकेतिक अभिव्यक्ति हो। यो माथि उल्लेखित उच्च तहको पूर्वीय दर्शनको उत्कृष्ट र समृद्ध अभिव्यक्ति पनि हो। यसले ईश्वरप्रतिको आस्था, कर्मप्रतिको आस्था र जीवनप्रतिको मोहबाट मुक्तिको प्रेरणा पनि दिन्छ। पूर्वीय दर्शनमा स्वर्ग, मर्त्य र पाताल लोकको गरिएको परिकल्पनाको सांकेतिक अभिव्यक्ति तर्फ पनि यसले संकेत गर्दछ। यसरी खप्तडी बस्नेतहरूले अपनाएको देवता र पूजा विधिहरू केवल धार्मिक आस्था र विश्वास मात्र नभएर जीवन, जगत्, कर्म आदिलाई बुझ्ने, बुझाउने र व्याख्या गर्ने अत्यन्तै उच्च तहको दार्शनिक चेतना पनि हो भन्न सकिन्छ। ________________________________________ सन्दर्भ सामग्रीहरू • (१) आचार्य, राजेन्द्र कुमार: पचहत्तर जिल्लाको लोककथा (संकलन र सम्पादन), २०७३, काठमाडौँ: ने.प्र.प्र. पृ. ११४-११५। • (२) खड्का, रामबहादुर: मष्ट संस्कृति र परम्परा। • (३) भट्टराई, विश्वनाथ: प्राचीन डोमेटी (डोटी) राज्यको राजनीतिक तथा सांस्कृतिक इतिहास (आलेख)। • (४) कार्की, तेज: के हो मष्ट संस्कृति? यस्तो छ यसको इतिहास (आलेख), golkhabar.com। • (५) मष्टो कुलदेवता प्रतिष्ठान: मष्टो इतिहास र संस्कृति। • (६) प्रज्ञा (पूर्णाङ्क ९७): वर्ष ४४, अङ्क २, २०६९ चैत। • (७) Regmi, D.R.: Medieval Nepal. • (८) Grierson, George Abraham: Linguistic Survey of India. • (९) Pokhrel, Balkrishna: Ancient Khas Culture. • (१०) Sharma, Balkrishna: The Origin of Khas System in Hinduism and its Relevance in the Present Context. • (११) Wikipedia: <nowiki>https://dty.wikipedia.org</nowiki> । [[विशेष:Contributions/&#126;2026-15382-66|&#126;2026-15382-66]] ([[प्रयोगकर्ता वार्ता:&#126;2026-15382-66|वार्तालाप]]) १५:४२, ११ मार्च २०२६ (नेपाली समय) == कौशिक गोत्र: इतिहास र परिचय राजेन्द्र बहादुर बस्नेत तुलसीपुर-६, दाङ == == कौशिक गोत्र: इतिहास र परिचय == '''राजेन्द्र बहादुर बस्नेत''' '''तुलसीपुर-६, दाङ''' कौशिक गोत्र के हो? यसको इतिहासको बारेमा धेरै मानिसहरूका लागि यो रहस्यको रूपमा रहेको पाइन्छ। आफूलाई कौशिक गोत्रका भन्नेहरूले पनि यसको बारेमा सामान्य जानकारी समेत राख्ने गरेको पाइँदैन। त्यसकारण सामान्य पाठकलाई जानकारी होस् भनेर यो सानो प्रयास गरिएको छ। भारतमा कौशिक वा उलूक एक सम्प्रदाय हो। प्राचीन भारतीय ग्रन्थहरूमा कुशिक नामका एक प्रख्यात मुनिको उल्लेख पाइन्छ, जो लकूलीशका शिष्य थिए। उनको नाममा उलूक सम्प्रदायको नाम कौशिक रह्यो। कुशिक नामका एक अर्का ऋषि पनि थिए, जो भगवान् विष्णुका भक्त र सामवेदी थिए। उनी ब्राह्मण थिए। उनको सामगान प्रसिद्ध थियो। उनको कथा तथा नारदको साम वा गायन सिक्ने कथा पनि प्रख्यात छ। कुशिक ऋषिका अनुयायी वा वंशजहरू पनि कौशिक भनिन्छन्। ब्रह्माका एक पुत्रको नाम कुश थियो, जो राजा पनि बने। यिनी कुशका वंशज पनि कौशिक भनिए। ब्रह्माका पुत्र भएका कारणले उनी कुश ब्राह्मण भए र उनका सन्तान कौशिक। कुशका चार पुत्र भए— कुशाम्ब, कुशनाभ, असुर्र्तजस र वसु। कौशिक गोत्रीय क्षत्रीय र ब्राह्मण दुवै पाइन्छन्, तर दुवैका पूर्वज विश्वामित्र थिए भन्ने कुरामा मतभेद पाइन्छ। ऋषि विश्वामित्रलाई पनि कौशिक भनिन्छ। विश्वामित्र क्षत्रीय थिए। गोत्र परम्परामा ब्राह्मणलाई छोडेर अन्य जातिहरूका मानिसको उनीहरूका गुरुहरूको नै गोत्र हुने गर्दछ, जस्तै: भगवान् रामको गोत्र उनका कुलगुरु वशिष्ठको नाममा रह्यो। अर्थात् भगवान् राम वशिष्ठ गोत्रका थिए। त्यस्तै प्रकारले विश्वामित्रको गोत्र पनि कौशिक भयो, किनभने ब्राह्मण कुलमा उत्पन्न भएका ऋषि कुशिक उनका गुरु थिए। यसैकारण ऋग्वेदमा उनलाई कौशिक भनिएको छ। उनलाई कौशिक भन्नुको अर्को कारण पनि छ। त्यस अनुसार विश्वामित्र ब्रह्माका एक पुत्र कुशका वंशज थिए, जसका कारण उनलाई कौशिक भनियो। केही ग्रन्थमा गाधिलाई कुशाम्बका पुत्र र अन्य केही ग्रन्थमा उनलाई कुशनाभका पुत्र बताइएको छ। यिनै गाधिका पुत्र विश्वामित्र थिए। विश्वामित्र जन्मले क्षत्रीय मान्दै आएको कारणले उनलाई ब्रह्माको पुत्र कुशका वंशज मान्न धेरै मानिस तयार छैनन्। किनभने यो कुरालाई मान्ने हो भने विश्वामित्रलाई ब्राह्मण मान्नुपर्ने हुन्छ, जो उनीहरू मान्न तयार छैनन् र यो विश्वामित्रलाई क्षत्रीय मानिरहेको परम्पराको विपरीत हुन जान्छ। हरिवंश पुराण र प्रायः अन्यत्र कतिपय ग्रन्थका अनुसार गाधि कुशाम्बका भाइ कुशिकका पुत्र थिए र इन्द्र स्वयम् गाधि बनेर अवतरित भएका थिए। यसबाट यो वंशको नाम कौशिक रह्यो। गाधिपुत्र विश्वामित्रलाई कौशिक भन्ने कारण यही थियो। हरिवंश पुराणको प्रथम पर्वको २७ औँ सर्गको श्लोक १२-१६ मा यसलाई स्पष्ट भाषामा उल्लेख छ। यसमा भनिएको छ कि कुशिकले इन्द्रको समान पुत्र पाउने इच्छाले तपस्या गर्न थाले, तब इन्द्र भयभीत भएर स्वयम् उनको पुत्र बनेर उत्पन्न भए। राजा कुशिकले एक हजार वर्ष तप गरेपछि मात्र इन्द्रको ध्यान कुशिकतिर गएको थियो। अति उग्र तप गरेर पुत्र पाउन उनी समर्थ देखेर सहस्राक्ष पुरन्दरले उनीमा आफ्नो अंश स्थापित गरे। यस प्रकार इन्द्र कुशिकका पुत्र बनेका थिए। (१३-१५) श्लोकमा भनिएको छ:<blockquote>''स गाधिरभवद् राजा मघवान् कौशिकः स्वयम्।'' ''पौरुः कुत्स्योऽभवद् भार्या गाधिस्तस्यामजायत।।''</blockquote>यदि विश्वामित्र जन्मजात क्षत्रीय थिएनन् भने सम्भव छ कुशाम्ब र कुशिक नामका अन्य कुनै व्यक्ति थिए होलान् जो क्षत्रीय थिए र ब्रह्माका पौत्र कुशाम्ब जो ब्राह्मण थिए, उनी अर्कै थिए। अनेकौँ ग्रन्थमा गाधिका पिताको नाम कुशनाभ तथा कुशनाभका पिताको नाम कुश तथा कुशका पिता ब्रह्माको उल्लेख पाइएको कारण भ्रम तथा विवादको स्थिति कायमै छ। यस प्रकार जो ब्राह्मण कौशिक गोत्रका हुन्, ती या ब्रह्माका पुत्र कुशका वंशज हुन् वा कुशिक ब्रह्मर्षिका सन्तान हुन्। कौशिक गोत्रीय ब्राह्मण कौशिक (विश्वामित्र) जो क्षत्रीय हुन्, उनका सन्तान हुन् भन्ने कुरा विश्वसनीय लाग्दैन। सम्भवतः कुशिक नामक ब्राह्मण विश्वामित्रका गुरु रहेका हुन सक्छन्, जसबाट विश्वामित्रको गोत्र कौशिक भएको होस्। तर कान्यकुब्ज तथा कतिपय ब्राह्मणहरू कौशिक गोत्रीय छन्। कतिपय विद्वान्‌ले उनीहरू कौशिकका सन्तान हुन् भन्ने कुरामा मतभेद राख्दछन्। जो कौशिक गोत्रीय क्षत्रीयहरू छन्, ती विश्वामित्रका वा क्षत्रीय राजा कुशिकका वा उनका पूर्वजका गुरु कुशिक ब्रह्मर्षिका सन्तान हुन्। अन्य कौशिक जातिहरूका पूर्वजका गुरु पनि सम्भवतः ब्रह्मर्षि कुशिक नै थिए। नेपालको कोशी नदीको किनारमा विश्वामित्रले तपस्या गरेर ऋषिको दर्जा प्राप्त भएको भन्ने उल्लेख छ। महाभारतमा पनि यो नदीको कौशिकी नामबाट उल्लेख गरेको पाइन्छ। कोशी नदीको किनारमा बस्ने भएको कारण त्यहाँका मानिसलाई कौशिक भनिएको भन्ने मत पनि पाइन्छ। प्राचीन उलूक वा कौशिक सम्प्रदाय तथा वैशेषिक शैव दर्शनसँग पनि कौशिकको सम्बन्ध पाइन्छ। कुनै कौशिकको सम्बन्ध कुशिक ब्रह्मर्षि र केहीको सम्बन्ध केवल सप्तकोशी नदीसँग रहन गयो। कौशिक 'उल्लू' वा लाटोकोसेरो नामक पक्षीलाई पनि भनिन्छ, तर यो पक्षी मूर्ख वा लाटो भने पटक्कै हुँदैन। === विश्वामित्र र कौशिक गोत्र === विश्वामित्र वैदिक कालका विख्यात ऋषि थिए। उनी महान् र तेजस्वी महापुरुष थिए। ऋषि धर्म ग्रहण गर्नुपूर्व उनी महान् प्रजावत्सल राजा थिए। उनले गायत्री मन्त्रको रचना गरेका थिए। '''क्षत्रीय राजाको रूपमा:''' प्रजापतिका पुत्र कुश (श्रीरामका पुत्र कुश होइनन्) का पुत्र कुशनाभका पुत्र राजा गाधि थिए। विश्वामित्र तिनै गाधिका पुत्र थिए। एकदिन राजा विश्वामित्रले आफ्नो सेना लिएर वशिष्ठ ऋषिको आश्रममा गए। विश्वामित्रले उनलाई प्रणाम गरेर त्यहीँ बसे। वशिष्ठ ऋषिले उनको यथोचित सत्कार गरे र उनलाई केही दिन आश्रममा बसेर आतिथ्य ग्रहण गर्ने अनुरोध गरे। आफूसँग रहेका धेरै सेनासहित बस्दा ऋषिलाई गाह्रो हुने ठानेर विश्वामित्रले विनम्रतापूर्वक बिदा हुने अनुमति मागे, तर वशिष्ठ ऋषिले अत्यधिक अनुरोध गरेको हुनाले केही दिनको लागि उनको अनुरोध स्वीकार गरे। वशिष्ठजीले नन्दिनी नामक गाईलाई आह्वान गरेर विश्वामित्र तथा उनका सेनाहरूका लागि ६ प्रकारका व्यञ्जन तथा सम्पूर्ण प्रकारका सुख-सुविधाको व्यवस्था गरिदिए। वशिष्ठको आतिथ्यले विश्वामित्र र उनीसँग आएका सबै मानिस प्रसन्न भए। नन्दिनी गाईको चमत्कार देखेर विश्वामित्रले त्यो गाई वशिष्ठसँग मागे, तर वशिष्ठले यो गाई कुनै हालतमा पनि दिन अस्वीकार गरे। वशिष्ठको यस्तो जवाफबाट विश्वामित्रले त्यो गाई जबरजस्ती पक्रेर ल्याउन आदेश दिए र उनका सैनिकले लौरोले हान्दै गाईलाई लैजान थाले। नन्दिनी गाई क्रोधित हुँदै सैनिकबाट आफ्नो बन्धन छुटाएर वशिष्ठकहाँ आएर विलाप गर्न थालिन्। वशिष्ठले भने, "हे नन्दिनी! यी राजा मेरा अतिथि हुन्, त्यसैले म यिनलाई श्राप दिन सक्दिनँ र यिनीसँग विशाल सेना छ, त्यसैले युद्धमा विजय हासिल गर्न पनि सक्दिनँ। म आफूलाई विवश अनुभव गरिरहेको छु।" उनका यी कुरा सुनेर नन्दिनीले वशिष्ठ ऋषिसँग आफूलाई लड्न अनुमति मागिन् र अन्य उपाय केही नदेखेपछि उनले अनुमति दिए। आज्ञा पाउनासाथ नन्दिनीले योगबलले अत्यन्त पराक्रमी मारक शस्त्रास्त्रहरूले युक्त योद्धा उत्पन्न गरिन् र तिनीहरूले शत्रुसेनालाई ध्वस्त पार्न थाले। आफ्नो सेनाको विनाश देखेर विश्वामित्रका सय पुत्र रिसाएर वशिष्ठलाई मार्न दौडिए। वशिष्ठले उनीहरूमध्ये एक जनालाई छोडेर सबैलाई भष्म गरिदिए। आफ्नो सेना तथा पुत्रहरूको विनाशपछि विश्वामित्र अत्यन्त दुःखी भए र छोरालाई राज्य सुम्पेर हिमालयको कन्दरामा कठोर तपस्या गरेर महादेवलाई खुसी पारेर उनीबाट दिव्य शक्तिहरूको साथै सम्पूर्ण धनुर्विद्याको ज्ञान प्राप्त गरे। ---- === नेपालका केही लोकप्रिय गोत्रहरू === * '''अगस्ति:''' ढुङ्गेल * '''अङ्गिरा:''' जोशी, शाही, सेढाईं, सौनक। * '''अत्रि:''' चापागाईं, मिश्र, अधिकारी, अर्याल (अर्जेल), वस्ती, गौतम, बम, भट्ट (पशुपति), खतिवडा, ओझा। * '''आत्रेय:''' देवकोटा, दुवाडी, अर्याल, भट्ट, खड्का (कालकोट), दुलाल, पौडेल, पोखरेल (पानी), शर्मा, सिग्देल, थापा (बगाले)। * '''उपमन्यु:''' मैनाली, ढकाल, बर्तौला, भट्ट (दुवाल), पाण्डे। * '''रवि:''' शाह, कल्याण (ठकुरी)। * '''साङ्ख्यायन:''' पाण्डे (देश)। * '''शाण्डिल्य:''' काफ्ले, पाठक, प्रसाईं, तिवारी। * '''भारद्वाज:''' अधिकारी, भट्ट (पुल्याई), चौलागाईं, देवकोटा, जमकरट्टेल, लोहनी, निरौला, पन्थी, पाण्डे (कुलेटा), पन्त, पोखरेल (दूध), शाही, शिवाकोटी, सुवेदी, थामी (अधिकारी), थपलिया, वाग्ले। * '''धनञ्जय:''' बस्याल, भुसाल, बस्नेत (खुलाल), बुढाथोकी (खुलाल), धमला, गुरागाईं, हुमागाईं, कार्की (खुलाल), खड्का (खुलाल), कुकुरकाटे, कुँवर, पङ्गेनी, रिजाल, थापा। * '''विश्वामित्र:''' भट्ट। * '''कश्यप:''' शाह, शाही, रायमाझी, घिमिरे, गोदार (थापा), कठायत, गर्तौला, अधिकारी (भँडारे, खिलचिने, कौबाली), बोगटी, बुढाथोकी (सोदारी), बडाल, भट्ट (कलौनी), मुस्याल, गड्तौला, हाडा, कुमाल, तिवारी। * '''कौण्डिन्य:''' आचार्य, न्यौपाने, प्याकुरेल, पनेरु, सापकोटा, भण्डारी (काला), सत्याल, मरासिनी, पराजुली, बास्कोटा, त्रिताल, खड्का, जोशी, खरेल, पाठक, थापा (बगाले र गाम्ले)। * '''कौशल्य:''' पाठक, थामी (क्षेत्री)। * '''कुण्डिन:''' त्रिताल, बन्जाडे। * '''कौशिक:''' खप्तडी (बस्नेत, खड्का, विष्ट, बुढाथोकी), रेग्मी, पाठक, गौडेल, भण्डारी, रिमाल, सन्जेल, शाही (सिँजापति), लामिछाने, ढुङ्गाना, धिताल, फुयाँल, तिवारी, माझी, लुइँटेल, थामी, पुडासैनी, बानियाँ, रघुवंशी, विडारी, बम (छत्याल ठकुरी), बास्ताकोटी। * '''गौतम:''' चन्द, बम (ठकुरी), दङ्गाल, पाण्डे (पल्लु), त्रिपाठी, तिवारी। * '''गर्ग:''' बास्तोला, लामिछाने, भुर्तेल, चुडाल, भट्ट (लामिछाने), खेतान, थापा (लामिछाने), रोका, गजुरेल। * '''गौतम:''' चन्द, त्रिपाठी, भेटुवाल, रिसाल, शाह (कास्की खण्ड)। * '''घृतकौशिक:''' सुतार, कार्की (सुतार), बराल, पण्डित, खनाल, नेपाल, बराइली। * '''पाराशर:''' धिमाल (खस), कार्की (लामा), कट्टेल, मरहट्टा। * '''वशिष्ठ:''' भण्डारी (थानसिङ्गे), भट्ट (ताप्लेजुङ्गे), हठ्ठराई, चालिसे, दवाडी, गैरे, गम्नाङ्गे, खरेल, मुडबरी, पाठक, राउत, सुयाल (घर्ती), सुयाल (थापा)। * '''माण्डव्य:''' बजगाईं, ज्ञवाली, पण्डित, कटुवाल, मास्के, पन्थी। * '''वत्स:''' भट्ट (नागर), दाहाल, दयाल, कँवर, खराली, लम्साल, राणा, रूपाखेती। ----[[विशेष:Contributions/&#126;2026-15382-66|&#126;2026-15382-66]] ([[प्रयोगकर्ता वार्ता:&#126;2026-15382-66|वार्तालाप]]) १९:०८, १२ मार्च २०२६ (नेपाली समय) == खसहरू ले कहिले देखि जनै लगाउन सुरु गरे ? के खसहरूले जनै लगाएको कारण खस सभ्यताको पतन भएको हो ? == राजेन्द्र बहादुर बस्नेत, तुलसीपुर उमनपा६ दाङ कहिले देखि जनै लगाउन लागेको हुन ? के खसहरुले जनै लगाएको कारण खस सभ्यता समाप्ति तिर लागेको हो ? बाहुनहरूले प्राचीन कालदेखि नै जनै लगाउँथे भन्ने कुरा प्रमाणित गर्न नेपालका प्राचीन शिलालेख र लिपिहरूमा पाईन्छ। लिच्छविकालीन शिलालेखहरू (ईशाको ५ औँ देखि ८ औँ शताब्दी)मा काठमाडौँ उपत्यका र आसपासका क्षेत्रमा भेटिएका चाँगुनारायण, पशुपति र हाडीगाउँका लिच्छविकालीन शिलालेखहरूमा 'उपनयन' (व्रतबन्ध), 'द्विज' (दुई पटक जन्मेको - जनै लगाएपछि दोस्रो जन्म मानिने), र 'अग्निहोत्र' जस्ता शब्दहरू उल्लेख छन्। यसले लिच्छवि कालमै नेपालमा रहेका ब्राह्मणहरूले वैदिक विधि अनुसार जनै लगाउने र यज्ञ गर्ने गरेको प्रमाण पाइन्छन् । मनुस्मृति, याज्ञवल्क्य स्मृति जस्ता प्राचीन कानुनी र सामाजिक ग्रन्थहरूमा ब्राह्मणका लागि गर्भाधानदेखि नै संस्कार सुरु भई ८ वर्षको उमेरमा जनै वा यज्ञोपवीत धारण गर्नुपर्ने अनिवार्य नियम लेखिएको छ। नेपालका ब्राह्मणहरूले सुरुदेखि नै यही शास्त्रीय नियम पालना गरेको इतिहास छ। प्राचीन खसहरू सुरुमा वैदिक हिन्दु नभई आफ्नै रैथाने 'मष्टो' संस्कृतिका अनुयायी (प्रकृति पूजक) थिए र उनीहरू जनै लगाउँदैनथे। उनीहरूले जनै लगाउन थालेको र तागाधारी क्षत्री बनेको इतिहासलाई पुष्टि गर्ने मुख्य प्रमाणहरू निम्न छन्: क. प्राचीन भारतीय शास्त्र र पुराणको प्रमाण (अवैदिक वा जनैविहीन अवस्था):- मनुस्मृतिको १० औँ अध्याय, श्लोक २२-४४मा खसहरूलाई 'व्रात्य क्षत्री' भनिएको छ। 'व्रात्य' को अर्थ हुन्छ - संस्कारबाट च्युत भएका वा उपनयन वा जनै धारण नगरिएका क्षत्री। महाभारतको कर्णपर्वमा महाभारतको युद्धमा खसहरूले भाग लिएको उल्लेख छ, तर उनीहरूलाई वैदिक नियम पालना नगर्ने, मदिरा पिउने र जनै नलगाउने 'म्लेच्छ' वा 'बर्बर' समुदायका रूपमा चित्रण गरिएको छ। यी प्राचीन प्रमाणहरूले प्रारम्भिक कालमा खसहरू वीर योद्धा क्षत्री भए पनि उनीहरू जनै लगाउँदैनथे भन्ने देखाउँछ। दुल्लुको कीर्तिस्तम्भ र ताम्रपत्र (बिसं. १४१४मा जुम्ला र दैलेख (सिञ्जा साम्राज्य) मा खस राजाहरू जस्तै: नागराज, अशोक चल्ल, पृथ्वी मल्ल का शिलालेख र ताम्रपत्रहरू भेटिएका छन्। सुरुमा बौद्ध धर्म मानेका खस राजाहरूले १३ औँ-१४ औँ शताब्दीतिर दक्षिणबाट आएका ब्राह्मणहरूलाई शरण दिएर हिन्दु धर्म अँगाल्न थाले। राजाहरूले ब्राह्मणहरूबाट दीक्षा लिएपछि आफूलाई 'राठौर', 'मल्ल' वा 'शाही' उपाधि दिएर जनै लगाउन थाले। तर, यो समयमा जनै लगाउने परम्परा राजपरिवार र उच्च भारदारहरूमा मात्र सीमित थियो, आम खस जनता (बस्नेत,थापा, कार्की, खड्का आदि) माझ पुगिसकेको थिएन। खसहरूले व्यापक रूपमा जनै लगाएर 'क्षत्री' को सामाजिक दर्जा पाएको प्रमाण गोर्खाली राज्यको विस्तार र राणा कालमा भेटिन्छ । 'खत्री' जातिको उत्पत्ति सम्बन्धी प्रमाणमा इतिहासमा ब्राह्मण पुरुष र खस महिलाबीच विवाह भएर जन्मिएका सन्तानलाई 'खत्री' वा 'खत्री क्षेत्री' भन्न थालियो। ब्राह्मण पिताले आफ्ना ती सन्तानलाई जनै (उपनयन) दिने अधिकार पाए। यो प्रक्रियाले पनि धेरै खसहरू बिस्तारै तागाधारी (जनै लगाउने) समूहमा प्रवेश गरे। जङ्गबहादुर राणाले बिसं १९१० (सन् १८५४) मा जारी गरेको 'मुलुकी ऐन' ले नेपालको सम्पूर्ण समाजलाई ५ वटा मुख्य वर्गमा विभाजन गर्‍यो, जसको शीर्ष स्थानमा 'तागाधारी' (जनै लगाउने जात) लाई राखियो। यस ऐनमार्फत राज्यले नै कानुनी रूपमा ब्राह्मण, ठकुरी र खसहरू (जसलाई 'क्षत्री' नाम दिइयो) लाई जनै लगाउने 'तागाधारी' को दर्जा दियो। ऐनमा जनै लगाउनेहरूका लागि सजाय कम हुने र जनै नलगाउने (मतवाली) हरूका लागि फरक कानुनी व्यवस्था गरियो। यही राज्यको नीति र कानुनका कारण खसहरूले जनै लगाउने परम्परालाई अनिवार्य र पूर्ण रूपमा अपनाए। हाल पनि हुम्ला, जुम्ला, कालीकोट र बझाङका विकट ग्रामीण क्षेत्रहरूमा 'पावई खस' वा 'मतवाली छेत्री' हरू बसोबास गर्छन्। उनीहरू आफूलाई छेत्री नै भन्छन् तर आज पनि जनै लगाउँदैनन् र मदिरा सेवन गर्छन्। इतिहासकार बालकृष्ण पोखरेल, बाबुराम आचार्य का अनुसार यी पावई खसहरू नै प्राचीन जनै नलगाउने 'खस' हरूका वास्तविक उत्तराधिकारी हुन्, जो जङ्गबहादुरको मुलुकी ऐनको पूर्ण प्रभावमा परेनन् वा आफ्नो पुरानो मष्टो संस्कृतिमै अडिग रहे। ऐतिहासिक प्रमाणहरूका आधारमा बाहुनहरूले प्राचीन काल (लिच्छवि काल र सोभन्दा अघि) देखि नै जनै लगाउँथे भने खस क्षत्रीहरूले १२ औँ शताब्दीदेखि बिस्तारै जनै लगाउन सुरु १९१०को मुलुकी ऐन लागू भएपछि मात्र सम्पूर्ण समुदायले अनिवार्य र कानुनी रूपमा जनै लगाउन थालेका हुन्। भारत र नेपालको भूगोल इतिहासमा सधैँ खुला र अन्तरसम्बन्धित रहेकाले खसहरूको ऐतिहासिक रूपान्तरण र उनीहरूले जनै लगाउन थालेको प्रसंगलाई बुझ्न भारतको उत्तराखण्ड (कुमाउँ-गढवाल), हिमाचल प्रदेश र कश्मिरसम्मको इतिहासलाई हेर्नुपर्ने हुन्छ। भारतमा खस र क्षत्रीहरूले जनै लगाउन थालेको इतिहास, त्यसका प्रमाण र सामाजिक प्रक्रियालाई निम्न अनुसार व्यापक रूपमा बुझ्न सकिन्छ:- प्राचीन भारतीय स्रोतहरूले भारतको उत्तरी पहाडी क्षेत्र (हिमालयन बेल्ट) मा बस्ने खसहरूलाई सुरुमा वैदिक हिन्दु समाजभन्दा बाहिरका अर्थात् जनै नलगाउने (अवेदिक) समुदायका रूपमा चित्रण गरेका छन्। कालीदासको 'कुमारसम्भव' र राजतरङ्गिणी: चौथो-पाँचौँ शताब्दीका महाकवि कालीदास र ११ औँ शताब्दीमा कल्हणले लेखेको कश्मिरको इतिहास 'राजतरङ्गिणी' मा खसहरूको उल्लेख छ। त्यहाँ उनीहरूलाई पहाडमा बस्ने, युद्धकलामा निपुण तर वैदिक नियम (जस्तै यज्ञ र उपनयन/जनै) पालना नगर्ने जातिको रूपमा वर्णन गरिएको छ। प्रसिद्ध इतिहासकार राहुल सांकृत्यायनले आफ्नो पुस्तक 'हिमालय परिचय' मा स्पष्ट लेखेका छन् कि कुमाउँ, गढवाल र हिमाचलका प्राचीन खसहरू 'मष्ट' र प्रकृति पूजक थिए। उनीहरूमा ब्राह्मणहरूको वर्चस्व हुनुअघि जनै लगाउने कुनै चलन थिएन। भारतको उत्तराखण्ड (कुमाउँ-गढवाल) र हिमाचलमा खसहरूले जनै लगाउन थालेको प्रक्रिया ९ औँ शताब्दीदेखि १४ औँ शताब्दीको बीचमा व्यापक रूपमा सुरु भएको मानिन्छ। यसका पछाडि मुख्य दुईवटा ऐतिहासिक कारण र प्रमाणहरू छन्: क. कत्युरी र चन्द राजाहरूको काल (९ औँ-१४ औँ शताब्दी) उत्तराखण्डमा ९ औँ शताब्दीतिर कत्युरी राजवंश र पछि चन्द राजवंश (कुमाउँमा) र पन्वार राजवंश (गढवालमा) को उदय भयो। यी राजाहरूले मैदान (भारतको समथर भूभाग) बाट आएका कान्यकुब्ज र गौड ब्राह्मणहरूलाई आफ्नो दरबारमा उच्च स्थान दिए। ती ब्राह्मणहरूले पहाडका शासक र वीर खसहरूलाई 'राजपुत' वा 'क्षत्री' को दर्जा दिएर उनीहरूको 'उपनयन संस्कार' (व्रतबन्ध) गराई जनै भिराइदिए। यसरी शासक वर्ग र सेनामा रहेका खसहरू सबैभन्दा पहिले तागाधारी बने। उत्तराखण्डको इतिहासमा समाजलाई दुई भागमा हेरिन्थ्यो— 'वैदिक राजपुत' (जो मैदानबाट आएका दाबी गर्थे) र 'खस राजपुत' (जो त्यहीँका रैथाने खस थिए)। सुरुमा वैदिक राजपुतहरूले खस राजपुतहरूलाई जनै लगाउने अधिकार दिँदैनथे। तर, सेनामा खसहरूको बाहुल्यता र उनीहरूको आर्थिक शक्ति बलियो भएपछि, १३ औँ-१४ औँ शताब्दीतिर स्थानीय ब्राह्मणहरूले ठूलो रकम जसलाई 'कर' वा 'भेटी' भनिन्थ्यो लिएर खसहरूलाई जनै लगाइदिन थाले। यसलाई उत्तराखण्डको इतिहासमा "जनै किन्ने प्रथा" को रूपमा समेत व्याख्या गरिएको छ, जहाँ आर्थिक रूपमा सक्षम खस परिवारले ब्राह्मण डाकेर जनै धारण गर्थे। खस क्षत्री र भारतका मैदानका परम्परागत क्षत्री (राजपुत) हरूको इतिहास अलि फरक छ: मैदानी क्षत्री (राजपुत/सूर्यवंशी/चन्द्रवंशी): भारतको राजस्थान, उत्तर प्रदेश र विहारका रैथाने क्षत्रीहरूले भने वैदिक काल (हजारौँ वर्ष पहिले) देखि नै जनै लगाउँथे। उनीहरू बाहुनजस्तै 'द्विज' मानिन्थे। गुप्त साम्राज्यको पतनपछि भारतमा धेरै विदेशी रैथाने जातिहरू (जस्तै हूण, गुर्जर आदि) शक्तिमा आए। उनीहरूलाई ब्राह्मणहरूले 'अग्निकुल' को यज्ञ गराएर 'राजपुत' (क्षत्री) को दर्जा दिए र जनै लगाइदिए। नेपाल र भारत (उत्तराखण्ड/हिमाचल) का खसहरूले जनै लगाउन थालेको ऐतिहासिक विकासक्रम निकै मिल्दोजुल्दो छ । भारत (कुमाउँ, गढवाल, हिमाचल) मष्टो/प्रकृति पूजक, जनैविहीन 'खस राजपुत' ९ औँ देखि १४ औँ शताब्दी कत्युरी र चन्द राजाहरूको कालमा मैदानबाट आएका ब्राह्मणहरूद्वारा क्षत्रीयकरण गरेको पाइन्छ। नेपाल (कर्णाली, सिञ्जा साम्राज्य र पूर्वतर्फ) मष्टो पूजक, मनुस्मृतिमा 'व्रात्य क्षत्री' (जनैविहीन) पाइन्छन । भारत र नेपाल दुवै क्षेत्रका खसहरू मूलत: जनै लगाउने जाति थिएनन्। उनीहरू रैथाने पहाडी योद्धा र प्रकृति पूजक थिए। जब ८ औँ-९ औँ शताब्दीदेखि भारतको मैदानी भागबाट मुसलमानहरूको आक्रमणका कारण वा अन्य कारणले ब्राह्मणहरू पहाड (उत्तराखण्ड, गढवाल हुँदै नेपालको कर्णाली) तिर उक्लिए, तब उनीहरूले पहाडका शक्तिशाली खसहरूलाई आफ्नो संरक्षणमा लिए। ब्राह्मणहरूले उनीहरूको वीरतालाई स्विकार्दै 'क्षत्री' को दर्जा दिए र धार्मिक रूपमा वैधता दिनका लागि जनै (यज्ञोपवीत) लगाइदिने परम्परा सुरु गरे। भारतको उत्तराखण्डमा यो प्रक्रिया नेपालको भन्दा २-३ सय वर्ष अघि (चन्द र कत्युरी कालमा) सुरु भइसकेको थियो भने नेपालमा यसले मुलुकी ऐन १९१० पछि मात्र देशव्यापी र अनिवार्य कानुनी रूप पायो। खसहरू प्रकृति पूजक र मष्टो संस्कृतिबाट जनै लगाउने 'तागाधारी क्षत्री' बन्ने यो ऐतिहासिक रूपान्तरणले नेपाल र भारत (उत्तराखण्ड/गढवाल) दुवै क्षेत्रको राजनीति र समाजमा निकै गहिरो र दीर्घकालीन प्रभाव पार्यो। यो केवल एउटा धागो (जनै) लगाउने विषय मात्र थिएन, यसले सिंगो सामाजिक संरचनालाई नै बदलिदियो। यसका मुख्य राजनीतिक र सामाजिक प्रभावहरूलाई निम्न बुँदाहरूमा बुझ्न सकिन्छ: 'ब्राह्मण-क्षत्री' (बाहुन-छेत्री) गठबन्धनको उदय खसहरूले जनै पाएर 'क्षत्री' को सामाजिक दर्जा पाएपछि पहाडी क्षेत्रमा एउटा शक्तिशाली राजनीतिक र प्रशासनिक गठबन्धन तयार भयो। सत्ता र शक्तिको बाँडफाँड: भारतका चन्द वा कत्युरी राजा हुन् या नेपालका शाह र राणा शासक— सबैले यही नीति अपनाए। खसहरू (थापा, बस्नेत, पाँडे, कार्की, विष्ट आदि) सेना र हतियार चलाउने 'शासक/योद्धा' बने भने उनीहरूलाई जनै दिने र सल्लाह दिने ब्राह्मणहरू 'गुरु/पुरोहित' र प्रशासनिक सल्लाहकार बने। नेपालको एकीकरण र गोर्खाली सेनाको विरताको जगमा यही खस-क्षत्रीहरूको बाहुल्यता थियो। जनै लगाएर 'पवित्र क्षत्री' को दर्जा पाएपछि उनीहरूमा हिन्दु राज्यको रक्षा र विस्तार गर्ने धार्मिक र राजनीतिक जोस थपियो। खसहरू तागाधारी बनेपछि समाजमा ठूलो विभेद र वर्गीकरणको रेखा कोरियो, जसलाई जंगबहादुर राणाको वि.सं. १९१० को मुलुकी ऐनले कानुनी रूप दियो। जनै लगाउने प्रचलनको शुरूवात ले 'तागाधारी' र 'मतवाली' को विभाजन बीच विभेदको सृजना सुरु भयाे । जनै लगाउने खसहरू समाजको माथिल्लो तप्कामा (तागाधारी) पुगे। हिजोसम्म सँगै बस्ने, सँगै खानपिन गर्ने अन्य पहाडी समुदाय (जस्तै मगर, गुरुङ, राई, लिम्बू आदि) लाई जनै नलगाउने 'मतवाली' (मदिरा सेवन गर्ने) को तल्लो दर्जामा राखियो। जनैधारी क्षत्री र बाहुनहरूले राज्यबाट कर छुट, जमिन (बिर्ता), र न्याय प्रणालीमा ठूलो सहुलियत पाए। उदाहरणका लागि, एउटै अपराधमा मतवाली वा दलितलाई मृत्युदण्ड वा कठोर शारीरिक सजाय हुँदा तागाधारी (बाहुन-छेत्री) लाई जनै र कपाल मुडेर देशनिकाला मात्र गरिन्थ्यो वा कम सजाय हुन्थ्यो। खसहरूको आफ्नै मौलिक संस्कृतिमा यसले सबैभन्दा ठूलो चोट पुर्‍यायो: खसहरूका कुलदेवता 'मष्टो' (१२ भाइ मष्टो) र प्रकृति पूजालाई बिस्तारै हिन्दुकरण गरियो। धामी झाँक्री बस्ने मष्टो संस्कृतिमा ब्रह्मा, विष्णु र शिवका कथाहरू जोडिए। आज पनि धेरै छेत्रीहरूले मष्टोलाई कुलदेवता त मान्छन्, तर पूजाको विधि धेरै हदसम्म वैदिक हिन्दुजस्तो बनिसकेको छ। जनै लगाउन थालेपछि र आफूलाई 'उच्च जात' दाबी गर्नका लागि खसहरूले आफ्ना पुराना परम्पराहरू जस्तै मदिरा चढाउने, मासु खाने कतिपय रैथाने तौरतरिकालाई 'तल्लो स्तरको' भन्दै त्याग्न थाले। 'खस' पहिचान हराएर 'छेत्री' पहिचानको उदय यो रूपान्तरणको सबैभन्दा रोचक प्रभाव के पर्यो भने, 'खस' शब्द नै समाजबाट बिस्तारै गायब भयो। राज्य र समाजले 'खस' भन्नुलाई अशिक्षित, संस्कारहीन वा जङ्गली हुनु जस्तो अर्थमा बुझ्न थाल्यो। त्यसैले, गौरवका साथ जनै भिरेका खसहरूले आफूलाई 'खस' भन्न छाडेर 'क्षत्री' वा 'छेत्री' भन्न रुचाए। यसले गर्दा नेपाल र भारतको उत्तराखण्ड दुवैतिर एउटा विशाल र ऐतिहासिक 'खस सभ्यता' को नाम मेटिएर त्यो केवल 'छेत्री/राजपुत' जातिमा संकुचित हुन पुग्यो। (भर्खरैका दशकहरूमा मात्र नेपालमा 'खस-आर्य' भन्दै यो पहिचान ब्युँताउने प्रयास सुरु भएको छ)। निष्कर्ष खस र क्षत्रीले जनै लगाउन थाल्नु भनेको केवल एउटा धार्मिक कृत्य मात्र थिएन। यो पहाडी क्षेत्रका शासक, सैनिक र सर्वसाधारण खसहरूलाई दक्षिण एसियाको विशाल हिन्दु सामाजिक र राजनीतिक मूलधारमा समाहित गर्ने एउटा अचम्मको 'मास्टरस्ट्रोक' (रणनीति) थियो। यसले बाहुन-छेत्रीलाई शताब्दीऔँसम्म सत्ता र समाजको शीर्ष स्थानमा त राख्यो, तर सँगसँगै नेपाल र भारतीय पहाडको प्राचीन, समतामूलक र प्रकृतिपूजक 'खस संस्कृति' लाई सधैँका लागि बदलिदियो। यो ऐतिहासिक रूपान्तरणको अर्को एउटा निकै रोचक र व्यावहारिक पक्ष छ, जसले नेपाल र भारत (उत्तराखण्ड/गढवाल) को ग्रामीण समाजलाई अझै पनि प्रभावित गरिरहेको छ। जब खसहरूलाई जनै दिएर 'तागाधारी क्षत्री' बनाउने प्रक्रिया चल्यो, त्यतिबेला सबै खसहरू एकैपटक वा एकै रूपमा हिन्दुकरण भएनन्। यसले गर्दा खस समुदायभित्रै पनि एउटा ठूलो सामाजिक वर्गीकरण (Divisions) जन्मायो, जसका अवशेषहरू आज पनि देख्न सकिन्छ: १. 'तागाधारी छेत्री' र 'मतवाली छेत्री' को विभाजन सबै खसहरूले जनै पाएनन् वा सबैले जनै स्वीकार गरेनन्। यसले गर्दा खसहरू दुई भागमा बाँडिए: तागाधारी छेत्री: जसले ब्राह्मणहरूबाट विधिपूर्वक व्रतबन्ध गराएर जनै लगाए, मदिरा त्यागे र आफूलाई 'उच्च जात' को रूपमा स्थापित गरे (जस्तै आजका अधिकांश थापा, बस्नेत, कार्की, खड्का आदि)। मतवाली छेत्री (वा पावई खस): जसले आफ्नो पुरानो मष्टो संस्कृति छाडेनन्, जनै लगाएनन् र मदिरा (मत) को सेवन जारी राखे। नेपालको कर्णाली क्षेत्र (जुम्ला, हुम्ला, कालिकोट) र भारतको उत्तराखण्डका विकट पहाडी गाउँहरूमा आज पनि यस्ता छेत्रीहरू छन्, जसको थर तागाधारी छेत्रीसँग मिल्छ (जस्तै रोकाया, बुढा, थापा) तर उनीहरू जनै लगाउँदैनन्। उनीहरूलाई जंगबहादुरको मुलुकी ऐनले पनि तल्लो दर्जामा राखेको थियो। २. भारत र नेपालको सामाजिक-राजनीतिक प्रभावमा भिन्नता यस रूपान्तरणले नेपाल र भारतमा पारेको राजनीतिक प्रभावको रूप अलि फरक रह्यो: नेपालमा केन्द्रिकृत सत्ता: नेपालमा गोर्खा राज्यको नेतृत्व र जंगबहादुरको मुलुकी ऐनका कारण बाहुन-छेत्री (तागाधारी) को यो गठबन्धन राज्यको केन्द्रिकृत सत्ता (काठमाडौँ) सम्म पुग्यो। सेना, अदालत, र प्रशासनमा उनीहरूको एकलौटीजस्तै वर्चस्व कायम भयो, जुन लोकतन्त्र र गणतन्त्र आउनुअघिसम्म निकै बलियो थियो। भारतमा 'ओबीसी' (OBC) को लडाईं: भारतको उत्तराखण्ड र हिमाचलमा भने परिस्थिति अलि फरक बन्यो। त्यहाँका खसहरूले आफूलाई 'राजपुत/क्षत्री' भनेर जनै त लगाए, तर भारत स्वतन्त्र भएपछि आरक्षण र राज्यको आर्थिक सुविधा पाउनका लागि उनीहरूले आफूलाई 'पछाडि पारिएको वर्ग' (Backward Class) वा 'खस' पहिचानमै राख्नुपर्ने माग गरे। आज उत्तराखण्डका धेरैजसो रैथाने खस राजपुतहरू राज्यको राजनीतिक र सामाजिक लाभका लागि आफ्नो प्राचीन खस पहिचानलाई कानुनी रूपमा ब्युँताउन संघर्ष गरिरहेका छन्। ३. वर्तमान समयमा यसको अर्थ आजको आधुनिक समाजमा जनै लगाउने वा नलगाउने कुरा व्यक्तिगत स्वतन्त्रता र धार्मिक आस्थाको विषय बनिसकेको छ। पुराना कानुनी विभेदहरू (जस्तै १९१० को मुलुकी ऐनका व्यवस्थाहरू) संविधानतः खारेज भइसकेका छन्। तर, इतिहासको दृष्टिकोणबाट हेर्दा, खस र क्षत्रीले जनै लगाउन थाल्नु भनेको एउटा प्राचीन पहाडी सभ्यता (जुन प्रकृति र मष्टोमा आधारित थियो) र गंगाको मैदानबाट आएको वैदिक सभ्यताबीचको ऐतिहासिक संलयन (Fusion) थियो। यसै संलयनले आजको आधुनिक नेपाली र पहाडी भारतीय संस्कृतिको जग बसालेको हो। धन्यवाद पढ्नुहुने सबैलाई !! राजेन्द्र बहादुर बस्नेत तुलसीपुर उ.म. नगरपालिका ६दाङ 74t6ff0wjhpmbajz24losbnyrxp3gl0 ढाँचा:Infobox international football competition 10 57896 1361463 1254250 2026-06-12T08:42:26Z पर्वत सुवेदी 31224 /* */ 1361463 wikitext text/x-wiki {{#invoke:infobox|infoboxTemplate | bodyclass = vcalendar | titleclass = summary | title = {{#if:{{{tourney_name|}}}|{{{year|}}} {{{tourney_name|}}} {{{yearr|}}} <includeonly>|{{PAGENAMEBASE}}</includeonly>}} | above = {{{other_titles|}}} | abovestyle = font-size: 100% | image = {{#invoke:InfoboxImage|InfoboxImage |image={{{image|}}} |size={{if empty|{{{image_size|}}}|{{{size|}}}}} |sizedefault=frameless |upright={{if empty|{{{upright|}}}|1}} |alt={{{alt|}}} |suppressplaceholder=yes}} | caption = {{{caption|}}} | header1 = {{#if:{{{country|}}}{{{city|}}}{{{num_teams|}}}{{{venues|}}}|Tournament details}} | label2 = Host countr{{#if:{{{country2|}}}|ies|y}} | data2 = {{#if:{{{country|}}}|{{{country}}}}}<!-- -->{{#if:{{{country2|}}}|<br />{{{country2|}}}}}<!-- -->{{#if:{{{country3|}}}|<br />{{{country3|}}}}}<!-- -->{{#if:{{{country4|}}}|<br />{{{country4|}}}}}<!-- -->{{#if:{{{country5|}}}|<br />{{{country5|}}}}}<!-- -->{{#if:{{{country6|}}}|<br />{{{country6|}}}}}<!-- -->{{#if:{{{country7|}}}|<br />{{{country7|}}}}}<!-- -->{{#if:{{{country8|}}}|<br />{{{country8|}}}}}<!-- -->{{#if:{{{country9|}}}|<br />{{{country9|}}}}}<!-- -->{{#if:{{{country10|}}}|<br />{{{country10|}}}}}<!-- -->{{#if:{{{country11|}}}|<br />{{{country11|}}}}}<!-- -->{{#if:{{{country12|}}}|<br />{{{country12|}}}}}<!-- -->{{#if:{{{country13|}}}|<br />{{{country13|}}}}}<!-- -->{{#if:{{{country14|}}}|<br />{{{country14|}}}}}<!-- -->{{#if:{{{country15|}}}|<br />{{{country15|}}}}} | label3 = City | data3 = {{{city|}}} | class3 = location | label4 = Dates | data4 = {{{dates|}}} | label5 = Teams | data5 = {{{num_teams|}}}{{#if: {{{confederations|}}}|&nbsp;(from {{{confederations}}} confederation{{#ifeq:{{{confederations}}}|1| |s}})}}{{#if: {{{sub-confederations|}}}|&nbsp;(from {{{sub-confederations}}} sub-confederation{{#ifeq:{{{sub-confederations}}}|1| |s}})}}{{#if: {{{associations|}}}|&nbsp;(from {{{associations}}} association{{#ifeq:{{{associations}}}|1| |s}})}} | label6 = Venue{{pluralize from text|{{{venues|}}}|likely=(s)|plural=s}} | data6 = {{{venues|}}}{{#if:{{{cities|}}}|&nbsp;(in {{{cities}}} host cit{{#ifeq: {{{cities}}}|1|y|ies}})}} | header7 = {{#if:{{{champion|}}}{{{champion_other|}}}|Final positions}} | label8 = {{#if:{{{American|}}}|Champion(s)|Champions}} | data8 = {{#if:{{{champion|}}}|{{fb|{{{champion|}}}|{{{champion-flagvar|}}}|name={{{champion-name|}}}}}{{#if: {{{count|}}}|{{nowrap| ({{ordinal|{{{count}}}}} title)}} }}{{#if:{{{champion-note|}}}|{{{champion-note}}}}} }} | label9 = {{#if:{{{American|}}}|Champion(s)|Champions}} | data9 = {{#if:{{{champion_other|}}}|{{{champion_other}}}{{#if: {{{count|}}}|{{nowrap| ({{ordinal|{{{count}}}}} title)}} }} }} | label10 = Runners-up | data10 = {{#if:{{{second|}}}|{{fb|{{{second|}}}|{{{second-flagvar|}}}|name={{{second-name|}}}}}{{#if:{{{second-note|}}}|{{{second-note}}}}} }} | label11 = Runners-up | data11 = {{#if:{{{second_other|}}}|{{{second_other|}}} }} | label12 = Third place | data12 = {{#if:{{{third|}}}|{{fb|{{{third|}}}|{{{third-flagvar|}}}|name={{{third-name|}}}}}{{#if:{{{third-note|}}}|{{{third-note}}}}} }} | label13 = Third place | data13 = {{#if:{{{third_other|}}}|{{{third_other|}}} }} | label14 = Fourth place | data14 = {{#if:{{{fourth|}}}|{{fb|{{{fourth|}}}|{{{fourth-flagvar|}}}|name={{{fourth-name|}}}}}{{#if:{{{fourth-note|}}}|{{{fourth-note}}}}} }} | label15 = Fourth place | data15 = {{#if:{{{fourth_other|}}}|{{{fourth_other|}}} }} | label16 = Promoted | data16 = {{#if:{{{promoted|}}}|{{{promoted|}}} }} | label17 = Relegated | data17 = {{#if:{{{relegated|}}}|{{{relegated|}}} }} | header18 = {{#if:{{{matches|}}}{{{goals|}}}{{{attendance|}}}{{{top_scorer|}}}{{{player|}}}|Tournament statistics}} | label19 = Matches&nbsp;played | data19 = {{#if:{{{matches|}}}|{{formatnum:{{{matches}}}}}{{{matches_footnote|}}}}} | label20 = Goals scored | data20 = {{#if:{{{goals|}}}|{{formatnum:{{{goals}}}}}{{#if:{{{matches|}}}|&nbsp;({{formatnum:{{#expr: {{if empty|{{{goals|}}}|0}} / {{if empty|{{{matches|}}}|1}} round 2}}}} per match)}}{{{goals_footnote|}}}}} | label21 = Attendance | data21 = {{#if:{{{attendance|}}}|{{formatnum: {{if empty|{{{attendance|}}}|0}}}}{{#if:{{{matches|}}}|&nbsp;({{formatnum: {{#expr: {{if empty|{{{attendance|}}}|0}} / {{if empty|{{{matches|}}}|1}} round 0}}}} per match) }} }} | label22 = Top scorer{{pluralize from text|{{{top_scorer|}}}|likely=(s)|plural=s}} | data22 = {{{top_scorer|}}} | class22 = attendee | label23 = Best player{{pluralize from text|{{{player|}}}|likely=(s)|plural=s}} | data23 = {{{player|}}} | class23 = attendee | label24 = Best young player | data24 = {{{young_player|}}} | class24 = attendee | label25 = Best [[Goalkeeper (association football)|goalkeeper]] | data25 = {{{goalkeeper|}}} | class25 = attendee | label26 = Fair play award | data26 = {{{fair_play|}}} | class26 = attendee | belowstyle = border-top:#bbb solid 1px | below = {{#if:{{{season_text|}}}|''{{{season_text|}}}'' {{clear}} }}{{#if:{{{prevseason|}}}|{{align|left|&larr; {{{prevseason|}}} }} | {{#if:{{{season_text|}}}|{{0|&larr; {{if empty|{{{nextseason|}}}|0000–00}}}}}} }}{{#if:{{{nextseason|}}}|{{align|right|{{{nextseason|}}} &rarr; }} | {{#if:{{{season_text|}}}|{{0|{{if empty|{{{prevseason|}}}|0000–00}} &rarr;}}}} }} {{#if:{{{prevseason2|}}}{{{nextseason2|}}}|{{clear}}{{#if:{{{season_text2|}}}|''{{{season_text2|}}}'' {{clear}} }}{{#if:{{{prevseason2|}}}|{{align|left|&larr; {{{prevseason2|}}} }} | {{#if:{{{season_text2|}}}|{{0|&larr; {{if empty|{{{nextseason2|}}}|0000–00}}}}}} }}{{#if:{{{nextseason2|}}}|{{align|right|{{{nextseason2|}}} &rarr; }} | {{#if:{{{season_text|}}}|{{0|{{if empty|{{{prevseason2|}}}|0000–00}} &rarr;}}}} }} }} {{#if:{{{updated|}}}|{{clear}}All statistics correct as of {{{updated}}}.}}{{#if:{{{extra information|}}}|{{clear}}{{{extra information}}}}} | decat = {{#if:{{{prevseason|}}}{{{nextseason|}}}|yes|no}} }}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using infobox international football competition with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Infobox international football competition]] with unknown parameter "_VALUE_"|ignoreblank=y| alt | American | associations | attendance | caption | champion | champion_other | champion-flagvar | champion-name | champion-note | cities | city | confederations | count | country | country10 | country11 | country12 | country13 | country14 | country15 | country2 | country3 | country4 | country5 | country6 | country7 | country8 | country9 | dates | extra information | fair_play | fourth | fourth_other | fourth-flagvar | fourth-name | fourth-note | goalkeeper | goals | goals_footnote | image | image_size | matches | matches_footnote | nextseason | nextseason2 | num_teams | other_titles | player | prevseason | prevseason2 | promoted | relegated | season_text | season_text2 | second | second_other | second-flagvar | second-name | second-note | size | sub-confederations | third | third_other | third-flagvar | third-name | third-note | top_scorer | tourney_name | updated | upright | venues | year | yearr | young_player }}<includeonly>{{Short description|International football competition|2=noreplace}}</includeonly><noinclude>{{documentation}}</noinclude> gimrbdzgiys38xbdn7671ipcurpdxj6 1361464 1361463 2026-06-12T08:45:59Z पर्वत सुवेदी 31224 [[Special:Contributions/पर्वत सुवेदी|पर्वत सुवेदी]] ([[User talk:पर्वत सुवेदी|वार्ता]])द्वारा [[Special:Diff/1361463|1361463]] संशोधनलाई खारेज गरियो 1361464 wikitext text/x-wiki {{#invoke:infobox|infoboxTemplate | bodyclass = vcalendar | titleclass = summary | title = {{#if:{{{tourney_name|}}}|{{{year|}}} {{{tourney_name|}}} {{{yearr|}}} <includeonly>|{{PAGENAMEBASE}}</includeonly>}} | above = {{{other_titles|}}} | abovestyle = font-size: 100% | image = {{#invoke:InfoboxImage|InfoboxImage |image={{{image|}}} |size={{{image_size|{{{size|}}}}}} |sizedefault=frameless |upright={{{upright|1}}} |alt={{{alt|}}} |suppressplaceholder=yes}} | caption = {{{caption|}}} | header1 = {{#if:{{{country|}}}{{{city|}}}{{{num_teams|}}}{{{venues|}}}|प्रतियोगिता विवरण}} | label2 = आयोजक राष्ट्र | data2 = {{#if:{{{country|}}}|{{{country}}}}}<!-- -->{{#if:{{{country2|}}}|<br />{{{country2|}}}}}<!-- -->{{#if:{{{country3|}}}|<br />{{{country3|}}}}}<!-- -->{{#if:{{{country4|}}}|<br />{{{country4|}}}}}<!-- -->{{#if:{{{country5|}}}|<br />{{{country5|}}}}}<!-- -->{{#if:{{{country6|}}}|<br />{{{country6|}}}}}<!-- -->{{#if:{{{country7|}}}|<br />{{{country7|}}}}}<!-- -->{{#if:{{{country8|}}}|<br />{{{country8|}}}}}<!-- -->{{#if:{{{country9|}}}|<br />{{{country9|}}}}}<!-- -->{{#if:{{{country10|}}}|<br />{{{country10|}}}}}<!-- -->{{#if:{{{country11|}}}|<br />{{{country11|}}}}}<!-- -->{{#if:{{{country12|}}}|<br />{{{country12|}}}}}<!-- -->{{#if:{{{country13|}}}|<br />{{{country13|}}}}}<!-- -->{{#if:{{{country14|}}}|<br />{{{country14|}}}}}<!-- -->{{#if:{{{country15|}}}|<br />{{{country15|}}}}} | label3 = सहर | data3 = {{{city|}}} | class3 = location | label4 = मिति | data4 = {{{dates|}}} | label5 = टोलीहरू | data5 = {{{num_teams|}}}{{#if: {{{confederations|}}}|({{{confederations}}} सङ्घ{{#ifeq:{{{confederations}}}|1| |हरू}}बाट)}}{{#if: {{{sub-confederations|}}}|({{{sub-confederations}}} उप-सङ्घ {{#ifeq:{{{sub-confederations}}}|1| |हरू}}बाट)}}{{#if: {{{associations|}}}|({{{associations}}} सङ्गठन{{#ifeq:{{{associations}}}|1| |हरू}}बाट)}} | label6 = स्थान(हरू) | data6 = {{{venues|}}}{{#if:{{{cities|}}}|&nbsp;({{{cities}}} आयोजक सहर{{#ifeq: {{{cities}}}|1|हरूमा}})}} | header7 = {{#if:{{{champion|}}}{{{champion_other|}}}|अन्तिम स्थान}} | label8 = {{#if:{{{American|}}}|विजेता(हरू)|विजेता}} | data8 = {{#if:{{{champion|}}}|{{fb|{{{champion|}}}|{{{champion-flagvar|}}}|name={{{champion-name|}}}}}{{#if: {{{count|}}}|{{nowrap| ({{ordinal|{{{count}}}}} उपाधि)}} }}{{#if:{{{champion-note|}}}|{{{champion-note}}}}} }} | label9 = {{#if:{{{American|}}}|विजेता(हरू)|विजेता}} | data9 = {{#if:{{{champion_other|}}}|{{{champion_other}}}{{#if: {{{count|}}}|{{nowrap| ({{ordinal|{{{count}}}}} उपाधि)}} }} }} | label10 = उप-विजेता | data10 = {{#if:{{{second|}}}|{{fb|{{{second|}}}|{{{second-flagvar|}}}|name={{{second-name|}}}}}{{#if:{{{second-note|}}}|{{{second-note}}}}} }} | label11 = उप-विजेता | data11 = {{#if:{{{second_other|}}}|{{{second_other|}}} }} | label12 = तेस्रो स्थान | data12 = {{#if:{{{third|}}}|{{fb|{{{third|}}}|{{{third-flagvar|}}}|name={{{third-name|}}}}}{{#if:{{{third-note|}}}|{{{third-note}}}}} }} | label13 = तेस्रो स्थान | data13 = {{#if:{{{third_other|}}}|{{{third_other|}}} }} | label14 = चौथो स्थान | data14 = {{#if:{{{fourth|}}}|{{fb|{{{fourth|}}}|{{{fourth-flagvar|}}}|name={{{fourth-name|}}}}}{{#if:{{{fourth-note|}}}|{{{fourth-note}}}}} }} | label15 = चौथो स्थान | data15 = {{#if:{{{fourth_other|}}}|{{{fourth_other|}}} }} | label16 = पदोन्नति | data16 = {{#if:{{{promoted|}}}|{{{promoted|}}} }} | label17 = पदघट | data17 = {{#if:{{{relegated|}}}|{{{relegated|}}} }} | header18 = {{#if:{{{matches|}}}{{{goals|}}}{{{attendance|}}}{{{top_scorer|}}}{{{player|}}}|प्रतियोगिता तथ्याङ्क}} | label19 = खेलिएका&nbsp;खेलहरू | data19 = {{#if:{{{matches|}}}|{{formatnum:{{{matches}}}}}{{{matches_footnote|}}}}} | label20 = गोल सङ्ख्या | data20 = {{#if:{{{goals|}}}|{{formatnum:{{{goals}}}}}{{#if:{{{matches|}}}|&nbsp;({{formatnum:{{#expr: {{{goals|0}}} / {{{matches|1}}} round 2}}}} प्रति खेल)}}{{{goals_footnote|}}}}} | label21 = उपस्थिति | data21 = {{#if:{{{attendance|}}}|{{formatnum: {{{attendance|0}}}}}{{#if:{{{matches|}}}|&nbsp;({{formatnum: {{#expr: {{{attendance|0}}} / {{{matches|1}}} round 0}}}} प्रति खेल) }} }} | label22 = शीर्ष गोलकर्ता(हरू) | data22 = {{{top_scorer|}}} | class22 = attendee | label23 = उत्कृष्ट खेलाडी(हरू) | data23 = {{{player|}}} | class23 = attendee | label24 = उत्कृष्ट युवा खेलाडी | data24 = {{{young_player|}}} | class24 = attendee | label25 = उत्कृष्ट [[गोलरक्षक (फुटबल)|गोलरक्षक]] | data25 = {{{goalkeeper|}}} | class25 = उपस्थिति | label26 = उत्कृष्ट खेल पुरस्कार | data26 = {{{fair_play|}}} | class26 = उपस्थिति | belowclass = noprint | below = {{#if:{{{prevseason|}}}|{{align|left|&larr; {{{prevseason|}}} }}}}{{#if:{{{nextseason|}}}|{{align|right|{{{nextseason|}}} &rarr; }}}} {{#if:{{{updated|}}}|{{clear}}तथ्याङ्कहरू {{{updated}}} सम्म अद्यावधिक गरिएको छ।}}{{#if:{{{extra information|}}}|{{clear}}{{{extra information}}}}} | decat = {{#if:{{{prevseason|}}}{{{nextseason|}}}|yes|no}} }}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using infobox international football competition with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Infobox international football competition]] with unknown parameter "_VALUE_"|ignoreblank=y| alt | American | associations | attendance | caption | champion | champion_other | champion-flagvar | champion-name | champion-note | cities | city | confederations | count | country | country10 | country11 | country12 | country13 | country14 | country15 | country2 | country3 | country4 | country5 | country6 | country7 | country8 | country9 | dates | extra information | fair_play | fourth | fourth_other | fourth-flagvar | fourth-name | fourth-note | goalkeeper | goals | goals_footnote | image | image_size | matches | matches_footnote | nextseason | num_teams | other_titles | player | prevseason | promoted | relegated | second | second_other | second-flagvar | second-name | second-note | size | sub-confederations | third | third_other | third-flagvar | third-name | third-note | top_scorer | tourney_name | updated | upright | venues | year | yearr | young_player }}<includeonly>{{Short description|International football competition|2=noreplace}}</includeonly><noinclude>{{documentation}}</noinclude> hg9x1elt4xv7j34m3o2dny6o5f9drl2 रुद्र पाण्डे 0 57991 1361488 1315616 2026-06-12T11:06:08Z Bishaldev100 28807 1361488 wikitext text/x-wiki {{Distinguish|text=[[रुद्रराज पाण्डे]], एक नेपाली शिक्षाविद्}} {{Infobox person | name = रूद्र पाण्डे | image = Rudra Pandey 2016.JPG | alt = | caption = | birth_name = | birth_date = | birth_place = | death_date = | death_place = | nationality = [[नेपाली]] | ethnicity = | education = [[मेहेरान विज्ञान तथा प्रविधि विश्वविद्यालय|मेहेरान विश्वविद्यालय]], [[नर्थ इस्टर्न विश्वविद्यालय]] | other_names = | occupation = | known_for = डिटुहकाइका सह-संस्थापक; [http://www.deerwalk.com डियरवाक] का संस्थापक; [[en:Deerwalk Institute of Technology|डियरवाक इन्स्टिच्युट अफ टेक्नोलोजीका]] संस्थापक; [http://hamroparty.org/ हाम्रो पार्टी] का संस्थापक मार्गप्रदर्शक }} '''रुद्र पाण्डे''', (नौविसे,धादिङ, १९६३मा नेपालमा पैदा भएका) वर्तमान [[डियरवाक]] इन्क <ref>[http://nepal.usembassy.gov/ep-20130403.html रुद्र पाण्डे अमेरिकी राजदुतावास प्रस्तुती] {{Webarchive|url=https://web.archive.org/web/20130911043305/http://nepal.usembassy.gov/ep-20130403.html |date=2013-09-11 }}</ref>, लेक्सिङ्गटन, म्यासाचुसेट्स स्थित एक स्वास्थ्य विश्लेषिकी कम्पनीका कार्यकारी अध्यक्षका रूपमा कार्यरत एक नेपाली उद्यमी हुन् <ref>[http://www.deerwalk.com/executive-team.php रुद्र पाण्डे कार्यकारी अधिकारीको रूपमा] {{Webarchive|url=https://web.archive.org/web/20130928125539/http://www.deerwalk.com/executive-team.php |date=2013-09-28 }}</ref>। उनी डियरवाक इन्टिच्युट अफ टेक्नोलोजी संस्थाका अध्यक्षको रूपमा पनि कार्यरत छन्।<ref>[http://www.dwit.edu.np/content.php?page=management रुद्र पाण्डे डियरवाक इन्टिच्युट अफ टेक्नोलोजीमा] {{Webarchive|url=https://web.archive.org/web/20130909073642/http://www.dwit.edu.np/content.php?page=management |date=2013-09-09 }}</ref> ==शिक्षा== पाण्डेले मेहरान इन्जिनियरिङ तथा प्रविधि विश्वविद्यालयबाट इलेक्ट्रोनिक्स इन्जिनियरिङ्ममा स्नातक र नर्थईस्टर्न विश्वविद्यालयबाट अर्थशास्त्रमा विद्यावारिधी गरेका छन्। ==व्यवसायीक जीवन== पहिले,पाण्डेले डिटुहकाईको सहसस्थापना गरे र मूख्य प्राविधिक अधिकारीकारूपमा कार्य गरे। जब डिटुहकाईको भेरिस्क एनालिटिक्समा विलय भयो <ref>[http://www.myrepublica.com/portal/?action=news_details&news_id=1114 डिटुहकाईको भेरिस्क एनालिटिक्समा विलय]</ref><ref>[http://www.veriskhealth.com/press-releases/iso-acquires-d2hawkeye-inc डिटुहकाईको भेरिस्क एनालिटिक्समा विलय प्रेस विज्ञप्ती] {{Webarchive|url=https://web.archive.org/web/20130928145509/http://www.veriskhealth.com/press-releases/iso-acquires-d2hawkeye-inc |date=2013-09-28 }}</ref>,डिटुहकाई भेरिस्क हेल्थ भयो जहाँ पाण्डेले मूख्य कार्यसञ्चालन अधिकारीको रूपमा सेवा गरे। आफ्नो व्यवसायिक जीवनको सुरुवातमा, पाण्डेले व्यवसायिक सिस्टम इन्जिनियर, डेटाबेस आर्किटेक्ट र परामर्शदाताका रूपमा कार्य गरेका छन्। ==पारिवारिक जीवन== पाण्डे आफ्नी श्रीमती मुना पाण्डेका साथमा, लेक्जिङ्टन म्यासेचुसेटमा बस्छन्। उनकी दुई छोरीहरू छन् जसको नाम एरिका पाण्डे र माहिका पाण्डे हो। ==सन्दर्भ== {{reflist}} [[श्रेणी:धादिङ जिल्लाका मानिसहरू]] 657t3sxn70yvbdli4ccwjbtyv9wvteu जेनेट एलन 0 68598 1361166 1309062 2026-06-11T13:56:22Z Bishaldev100 28807 /* */ 1361166 wikitext text/x-wiki {{Infobox officeholder |name = जेनेट एलन |image = Janet Yellen official portrait.jpg |office = [[फेडरल रिजर्भका अध्यक्ष|फेडरल रिजर्वको अध्यक्ष]] |president = [[बाराक ओबामा]] |deputy = स्टान्ले फिसर |term_start = फेब्रुअरी ३, २०१४ |term_end = फेब्रुअरी ३, २०१८ |predecessor = [[बेन बर्नान्की]] |successor = [[जेरोमी पावेल]] |office1 = [[फेडरल रिजर्व प्रणाली]]को उपाध्यक्ष |president1 = [[बाराक ओबामा]] |term_start1 = अक्टोबर ४,२०१० |term_end1 = फेब्रुअरी ३, २०१४ |predecessor1 = डोनाल्ड कोन |successor1 = स्टान्ले फिसर |office2 = [[फेडरल रिजर्व बैङ्क सान फ्रान्सिस्को]]को अध्यक्ष |term_start2 = जुन १४,२००४ |term_end2 = अक्टोबर ४,२०१० |predecessor2 = रोबर्ट पेरी |successor2 = जोन विलियम्स |office3 = [[आर्थिक सल्लाहकारहरूको परिषद]] अध्यक्ष |president3 = [[बिल क्लिन्टन]] |term_start3 = फेब्रुअरी १८,१९९७ |term_end3 = अगस्त ३,१९९९ |predecessor3 = जोसेफ स्टिग्लिज |successor3 = मार्टिन बेली |birthname = जेनेट लोइज एलन |birth_date = सन् १९४६ अगस्त १३ |birth_place = {{nowrap|[[न्युयोर्क सहर|न्यु योर्क सहर]], संयुक्त राज्य}} |death_date = |death_place = |party = [[डेमोक्रेटिक पार्टी (अमेरिका)|डेमोक्रेटिक]] |spouse = जर्ज एकरलफ |religion = |alma_mater = ब्राउन विश्वविद्यालय<br />एल विश्वविद्यालय }} '''जेनेट लोइज एलन''' (जन्म अगस्त १३, १९४६) एक अमेरिकी [[अर्थशास्त्री]] हुन् जसले २०२१ देखि२०२५ सम्म सेक्रेटरी अफ ट्रेजरी को रुपमा काम गरिन् । उनी २०१४ देखि २०१८ सम्म [[फेडरल रिजर्भका अध्यक्ष|फेडरल रिजर्व प्रणालीको गवर्नरहरू]]को प्रमुखको रूपमा काम गरिन् । यसभन्दा पहिले उनी [[फेडरल रिजर्भ|फेडरल रिजर्व]]को उपाध्यक्षको रूपमा सन् २०१० देखि २०१४ सम्म कार्यरत थिइन् । सन् २०१४ जनवरी ६ मा [[अमेरिकी सिनेट|संयुक्त राज्य सिनेट]]ले एलनलाई फेडरल रिजर्भको प्रमुखमा पारित गरेको थियो । <ref>{{cite news|title=Senate Confirms Yellen as Fed Chairwoman|url=http://www.nytimes.com/2014/01/07/business/economy/Yellen-Senate-Vote.html?_r=0|publisher=New York Times|accessdate=January 6, 2014|first=Annie|last=Lowrey}}</ref> एलनले फेब्रुअरी ३,२०१४ मा पहिलो महिलाको रूपमा [[फेडरल रिजर्भ]] प्रमुख पदमा बहाल भएकी थिइन् ।<ref>[http://finance.yahoo.com/news/yellen-takes-over-fed-bernanke-departs-154802812.html Yellen Takes Over Federal Reserve As Bernanke Departs]</ref> नोभेम्बर ३०, २०२० मा, राष्ट्रपति-निर्वाचित [[जो बाइडेन]]ले येलेनलाई सेक्रेटरी अफ ट्रेजरी (अर्थमन्त्रीको समतुल्य)को रूपमा मनोनित गरे; उनलाई जनवरी २५, २०२१ मा [[अमेरिकी सिनेट]]ले अनुमोदन गर्यो र भोलिपल्ट पदभार ग्रहण गरिन् ।<ref name="FirstPerson">{{Cite press release|author=<!--Not stated-->|title=Janet L. Yellen Sworn In As 78th Secretary of the United States Department of the Treasury|url=https://home.treasury.gov/news/press-releases/jy0002|url-status=live|location=Washington, D.C.|publisher=U.S. Department of the Treasury|date=January 26, 2021|archive-url=https://web.archive.org/web/20210127105142/https://home.treasury.gov/news/press-releases/jy0002|archive-date=January 27, 2021|access-date=January 28, 2021}}</ref> ==प्रारम्भिक जीवन== ==सन्दर्भ सामग्री== {{reflist}} ==बाह्य कडीहरू== {{Commons category|Janet Yellen|जेनेट एलन}} * [http://www.federalreserve.gov/aboutthefed/bios/board/yellen.htm जेनेट एलन] {{Webarchive|url=https://web.archive.org/web/20121201045938/http://www.federalreserve.gov/aboutthefed/bios/board/yellen.htm |date=2012-12-01 }} फेडरल रिजर्भ प्रणालीमा {{Commonscat|Janet Yellen}} [[श्रेणी:विश्वका प्रभावशाली महिलाहरू]] [[श्रेणी:अमेरिकी केन्द्रीय बैङ्कका अध्यक्षहरू]] [[श्रेणी:बाइडेन प्रशासन मन्त्रिपरिषद्का सदस्यहरू]] g69el95uqxbo74ygdtjkap9u09sg1ey युरोपेली केन्द्रीय बैङ्कका प्रमुख 0 70802 1361169 1276597 2026-06-11T14:01:32Z Bishaldev100 28807 /* सूची */ 1361169 wikitext text/x-wiki {{Infobox Political post |post = अध्यक्ष |body = केन्द्रीय युरोपेली बैङ्क |insignia = |insigniasize = 130px |insigniacaption = Current Presidency logo |termlength = आठ वर्ष,गैर-अक्षय |image = File:Christine_Lagarde_(cropped).jpg |incumbent = [[क्रिस्टिन लागार्द]] |formation = |inaugural = [[विम डुइसेनबर्ग]] |website = }} '''केन्द्रीय युरोपेली बैङ्कका प्रमुख''' [[केन्द्रीय युरोपेली बैङ्क]]को प्रमुख हुन्छन् । [[युरोपेली सङ्घ]]को युरोजोनमा [[युरो]]को प्रबन्धन र मुद्रा नीतिको लागि यो सङ्घ जिम्मेवार निकाय हो । ==भूमिका र नियुक्ति== यस सङ्घको अध्यक्ष कार्यकारी बोर्ड, परिचालक परिषद र सामान्य परिषदको प्रमुख हुन्छ । उनी लोकप्रिय मतले निर्वाचित हुदैनन् । उनी विदेशमा भएको बैङ्कहरू पनि प्रतिनिधित्व गर्छन । वास्तविक युरो अपनाएका सदस्य राष्ट्रको कुनै एक प्रसिद्ध व्यक्तिलाई [[युरोपेली सङ्घ]]का आधिकारिक व्यक्तिहरूद्वारा बहुमतको आधारमा आठ वर्षको अवधिको लागि गैर-अक्षय नियुक्त गर्ने गरिन्छ ।<ref>[[:s:Consolidated protocols, annexes and declarations attached to the treaties of the European Union/Protocols#PROTOCOL (No 4) ON THE STATUTE OF THE EUROPEAN SYSTEM OF CENTRAL BANKS AND OF THE EUROPEAN CENTRAL BANK|Protocol 4 of the consolidated European treaties]]</ref> ==सूची== सन् १९९८ जुन १ मा स्थापना काल देखि [[युरोपेली केन्द्रीय बैंक|बैङ्क]]का अध्यक्षहरूको सूची: {| class="wikitable" |- ! # ! style="width:60px;"| चित्र ! style="width:150px;"|अध्यक्ष ! राज्य ! पदासिन ! पद छोडेको ! |- !rowspan=2| १ |rowspan=2| [[File:Wim Duisenberg.jpg|70px]] |rowspan=2| [[विम डुइसेनबर्ग]] | rowspan="2" | {{flag|नेदरल्यान्ड}} | १ जुन १९९८ | ३१ अक्टोबर २००३ | rowspan="2" |पहिले नेदरल्यान्डको अर्थ मन्त्री, नेदरल्यान्ड बैङ्कका अध्यक्ष तथा [[युरोपेली मुद्रा संस्थान]]को अध्यक्ष |- | colspan="2" |{{age in years and days|1998|6|1|2003|10|31}} |- !rowspan=2| २ |rowspan=2| [[File:Jean-Claude Trichet - World Economic Forum Annual Meeting Davos 2010.jpg|70px]] |rowspan=2| [[जीन-क्लाउडे त्रिचेत]] | rowspan="2" | {{flag|फ्रान्स}} | १ नोभेम्बर २००३ | ३१ अक्टोबर २०११ | rowspan="2" |पहिले तिस समुहका सदस्य तथा फ्रान्स बैङ्कका गवर्नर |- | colspan="2" |{{age in years and days|2003|11|1|2011|10|31}} |- !rowspan=2| ३ |rowspan=2| [[File:Mario Draghi World Economic Forum 2013 crop.jpg|70px]] |rowspan=2| [[मारियो द्रागी]] | rowspan="2" | {{flag|इटाली}} | १ नोभेम्बर २०११ | ३१ अक्टोबर २०१९ | rowspan="2" |गोल्डम्यान स्याक्सका प्रबन्धक, [[विश्व बैङ्क]]का कार्यकारी निर्देशक तथा [[बैङ्क अफ इटाली]]का गवर्नर |- | colspan="2" |{{age in years and days|2011|11|1|2019|11|01}} |- ! rowspan="2" |4 | rowspan="2" |[[File:Christine_Lagarde_(cropped).jpg|link=https://en.wikipedia.org/wiki/File:Christine_Lagarde_(cropped).jpg|97x97px]] | rowspan="2" |[[क्रिस्टिन लागार्द]] '''[[:en:Christine_Lagarde|Christine Lagarde]]''' {{small|(1956–)}} | rowspan="2" |{{flag|फ्रान्स}} |१ नोभेम्बर २०१९ |''Incumbent'' | rowspan="2" |{{Collapsible list | title = पृष्ठभुमि|फ्रान्सको बाणिज्य मन्त्री; <br> अर्थमन्त्री ; <br> अन्तरास्ट्रिय मुद्रा कोषको निर्देशक. }} |- | colspan="2" |{{age in years and days|2019|11|1}} |} ==यो पनि हेर्नुहोस्== * [[फेडरल रिजर्भका अध्यक्ष]] ==सन्दर्भ सामग्री== {{reflist}} {{ढाँचा:European Union topics}} [[श्रेणी:युरोपेली केन्द्रीय बैङ्कका प्रमुख]] 3v7w29ba3ugto6x14w9y869q2b7x7ai फेडरल रिजर्भका अध्यक्ष 0 71877 1361164 1321849 2026-06-11T13:52:48Z Bishaldev100 28807 /* */ 1361164 wikitext text/x-wiki {{Infobox official post | post = अध्यक्ष | body = अमेरिकी केन्द्रीय बैङ्क प्रणालीको गवर्नरहरूको समिति | flag = Flag_of_the_United_States_Federal_Reserve.svg | flagcaption = [[अमेरिकी केन्द्रीय बैङ्क प्रणाली]]को झण्डा | insignia = Seal of the United States Federal Reserve Board.svg | insigniacaption = [[अमेरिकी केन्द्रीय बैङ्क प्रणाली|अमेरिकी केन्द्रीय बैङ्क प्रणालीको गवर्नरहरू]]को छाप | image = 2026 Kevin Warsh at the White House on May 22 (cropped).jpg | incumbent = [[केभिन वार्स]] | incumbentsince = सन् २०२६ मे २२ | appointer = [[अमेरिकाका राष्ट्रपतिह‍रूको सूची|अमेरिकाका राष्ट्रपति]] | formation = सन् १९१४ अगस्त १० | first = [[चार्ल्स सम्नर ह्याम्लिन]] | salary = $२,०१,७००<ref>http://www.federalreserve.gov/faqs/about_12591.htm</ref> (2014) | website = [http://www.federalreserve.gov/aboutthefed/bios/board/yellen.htm वेब] }} '''अमेरिकी केन्द्रीय बैङ्क प्रणालीको गवर्नरहरूको अध्यक्ष''' [[संयुक्त राज्य अमेरिका|अमेरिका]] [[केन्द्रीय बैङ्क|केन्द्रीय बैङ्क प्रणाली]]को [[फेडरल रिजर्भ]]को प्रमुख हुन्छ। सामन्य बोलचालको भाषमा यसको प्रमुखलाई "फेडको अध्यक्ष", "फेड अध्यक्ष" तथा "फेड प्रमुख" पनि भन्ने गरिन्छ। यस प्रणालीको [[अध्यक्ष (कर्मचारी))|अध्यक्ष]] [[अमेरिकी केन्द्रीय बैङ्क प्रणाली|अमेरिकी केन्द्रीय बैङ्क प्रणालीको गवर्नरहरू]]को "सक्रिय कार्यकारी कर्मचारी" हुन्छ।<ref>see {{usc|12|242}}</ref> हाल यसको प्रमुख [[जेरोमी पावेल]] हुन्। ==सन् १९३५ को पुनर्गठन== {{ठुटो}} ==नियुक्ति प्रक्रिया== ==अमेरिकी केन्द्रीय बैङ्कको अध्यक्षहरूको सूची== फेडरल रिजर्भको बोर्ड अफ गभर्नरको अध्यक्षहरूको सूची निम्नानुसार छ। अध्यक्षको कार्यकाल चार वर्षको हुन्छ, तर निरन्तर कयौं चार वर्षको लागि पुनर्नियुक्त हुन सक्छन्। सन् १९१४ मा फेडरल रिजर्भको स्थापना भएपछिका अध्यक्षहरू।{{efn|अध्यक्षलाई सुरुवातमा १९३५ अगस्ट २३ सम्म "गभर्नर" भनिन्थ्यो र त्यसपछि "अध्यक्ष " भन्न थालियो।}}<ref name="Chairs">{{cite web |title = Chairs |work = Membership of the Board of Governors of the Federal Reserve System, 1914–present |publisher = The Federal Reserve Board |date = February 5, 2018 |url=http://www.federalreserve.gov/aboutthefed/bios/board/boardmembership.htm |access-date = February 6, 2018}}</ref> {| class="wikitable" style="text-align:center" ! rowspan="2" |{{No.}} ! rowspan="2" |चित्र ! rowspan="2" |नाम<br />{{small|(birth–death)}} ! colspan="2" |Term of office ! rowspan="2" |पदावधि ! rowspan="2" |First appointed by |- !कार्यकाल सुरु !कार्यकाल अन्त्य |- !- |[[File:William-gibbs-mcadoo-desk.jpg|link=https://en.wikipedia.org/wiki/File:William-gibbs-mcadoo-desk.jpg|122x122px]] |'''[[:en:William_Gibbs_McAdoo|{{efn|name=fn1}}]]''' '''[[:en:William_Gibbs_McAdoo|विलियम गिब्स म्याक अडु]]'''{{efn|name=fn1}} {{small|(1863–1941)}} |December २३, १९१३ |अगस्ट १०, १९१४ |{{age in years and days|1913|12|23|1914|8|10}} ! style="font-weight:normal" |''[[:en:Ex_officio_member|पदेन सदस्य]]'' |- !१ |[[File:HAMLIN,_CHARLES_S._ASSISTANT_SECRETARY_OF_THE_TREASURY,_1913-_LCCN2016864808_(cropped).jpg|link=https://en.wikipedia.org/wiki/File:HAMLIN,_CHARLES_S._ASSISTANT_SECRETARY_OF_THE_TREASURY,_1913-_LCCN2016864808_(cropped).jpg|124x124px]] |'''[[:en:Charles_Sumner_Hamlin|चार्ल्स समनर ह्यामलिन]]'''{{efn|name=fn2}}{{small|(1861–1938)}} |अगस्ट १०, १९१४ |अगस्ट ९, १९१६ |{{age in years and days|1914|8|10|1916|8|9}} ! rowspan="2" style="font-weight:normal" |[[:en:Woodrow_Wilson|Woodrow Wilson]] |- !२ |[[File:William_P.G._Harding.jpg|link=https://en.wikipedia.org/wiki/File:William_P.G._Harding.jpg|120x120px]] |'''[[:en:William_P._G._Harding|विलियम पी.जी. हार्डिङ]]'''{{efn|name=fn3}}{{small|(1864–1930)}} |अगस्ट १०, १९१६ |अगस्ट ९, १९२२ |{{age in years and days|1916|8|10|1922|8|9}} |- !३ |[[File:Daniel_R._Crissinger_cropped.jpg|link=https://en.wikipedia.org/wiki/File:Daniel_R._Crissinger_cropped.jpg|122x122px]] |'''[[:en:Daniel_Richard_Crissinger|डेनियल रिचार्ड क्रिसिन्जर]]''' {{efn|name=fn4}}{{small|(1860–1942)}} |May १, १९२३ |September १५, १९२७ |{{age in years and days|1923|5|1|1927|9|15}} ! style="font-weight:normal" |[[:en:Warren_G._Harding|Warren G. Harding]] |- !४ |[[File:Chair_Roy_A_Young_140501.jpg|link=https://en.wikipedia.org/wiki/File:Chair_Roy_A_Young_140501.jpg|118x118px]] |'''[[:en:Roy_A._Young|रोय ए. योङ]]'''{{small|(1882–1960)}} |अक्टोबर ४, १९२७ |अगस्ट ३१, १९३० |{{age in years and days|1927|10|4|1930|8|31}} ! style="font-weight:normal" |[[:en:Calvin_Coolidge|Calvin Coolidge]] |- !५ |[[File:Portrait_of_Eugene_Meyer.jpg|link=https://en.wikipedia.org/wiki/File:Portrait_of_Eugene_Meyer.jpg|120x120px]] |'''[[:en:Eugene_Meyer_(financier)|इउजिन मेएर]]''' {{small|(1875–1959)}} |September १६, १९३० |May १०, १९३३ |{{age in years and days|1930|9|16|1933|5|10}} ! style="font-weight:normal" |[[हर्बर्ट हुबर]] |- !६ |[[File:Eugene_R_Black_1934_(cropped).jpg|link=https://en.wikipedia.org/wiki/File:Eugene_R_Black_1934_(cropped).jpg|111x111px]] |'''[[:en:Eugene_Robert_Black|इउजिन रोबर्ट ब्ल्याक]]'''{{small|(1873–1934)}} |May १९, १९३३ |अगस्ट १५, १९३४ |{{age in years and days|1933|5|19|1934|8|15}} ! rowspan="2" style="font-weight:normal" |[[फ्र्याङ्क्लिन डी. रुजबेल्ट]] |- !७ |[[File:Marriner_Eccles_(cropped).jpg|link=https://en.wikipedia.org/wiki/File:Marriner_Eccles_(cropped).jpg|117x117px]] |'''[[:en:Marriner_S._Eccles|मारिनर एस. एक्लेस]]''' {{efn|name=fn2}}{{small|(1890–1977)}} |November १५, १९३४ |जनवरी ३१, १९४८{{efn|Served as ''chairman pro tempore'' from February 3, 1948 to April 15, 1948.}} |{{age in years and days|1934|11|15|1948|1|31}} |- !८ |[[File:00035_DUP_(14083184875).jpg|link=https://en.wikipedia.org/wiki/File:00035_DUP_(14083184875).jpg|132x132px]] |'''[[:en:Thomas_B._McCabe|थोमस बि. म्याक केब]]'''{{small|(1893–1982)}} |April १५, १९४८ |मार्च ३१, १९५१ |{{age in years and days|1948|4|15|1951|3|31}} ! rowspan="2" style="font-weight:normal" |[[ह्यारी एस ट्रुम्यान]] |- !९ |[[File:William_McChesney_Martin_jr.jpg|link=https://en.wikipedia.org/wiki/File:William_McChesney_Martin_jr.jpg|127x127px]] |'''[[:en:William_McChesney_Martin|विलियम म्याकचेस्नी मार्टिन]]''' {{small|(1906–1998)}} |April २, १९५१ |जनवरी ३१, १९७० |{{age in years and days|1951|4|2|1970|1|31}} |- !१० |[[File:ArthurBurns_USArmyPhoto_1955.jpg|link=https://en.wikipedia.org/wiki/File:ArthurBurns_USArmyPhoto_1955.jpg|105x105px]] |'''[[:en:Arthur_F._Burns|आर्थर एफ. बर्न्स]]''' {{small|(1904–1987)}} |फेब्रुअरी १, १९७० |जनवरी ३१, १९७८{{efn|Served as ''chairman pro tempore'' from February 1, 1978 to March 7, 1978, and remained a member of the Board until March 31, 1978.}} |{{age in years and days|1970|2|1|1978|1|31}} ! style="font-weight:normal" |[[रिचार्ड निक्सन]] |- !११ |[[File:G._William_Miller.jpg|link=https://en.wikipedia.org/wiki/File:G._William_Miller.jpg|106x106px]] |'''[[:en:G._William_Miller|जि. विलियम मिलर]]''' {{small|(1925–2006)}} |मार्च ८, १९७८ |अगस्ट ६, १९७९ |{{age in years and days|1978|3|8|1979|8|6}} ! rowspan="2" style="font-weight:normal" |[[जिम्मी कार्टर]] |- !१२ |[[File:Paulvolcker.jpg|link=https://en.wikipedia.org/wiki/File:Paulvolcker.jpg|117x117px]] |'''[[:en:Paul_Volcker|पल भोलकर]]'''{{small|(1927–2019)}} |अगस्ट ६, १९७९ |अगस्ट ११, १९८७ |{{age in years and days|1979|8|6|1987|8|11}} |- !१३ |[[File:Alan_Greenspan_color_photo_portrait.jpg|link=https://en.wikipedia.org/wiki/File:Alan_Greenspan_color_photo_portrait.jpg|119x119px]] |'''[[:en:Alan_Greenspan|एलन ग्रिनस्प्यान]]'''{{small|(born 1926)}} |अगस्ट ११, १९८७ |जनवरी ३१, २००६{{efn|Served as ''chairman pro tempore'' from March 3, 1996 to June 20, 1996, while awaiting confirmation by the United States Senate for his third term as chairman.}} |{{age in years and days|1987|8|11|2006|1|31}} ! style="font-weight:normal" |[[रोनाल्ड रेगन]] |- !१४ |[[File:Ben_Bernanke_official_portrait.jpg|link=https://en.wikipedia.org/wiki/File:Ben_Bernanke_official_portrait.jpg|113x113px]] |[[बेन बर्नान्की]]{{efn|name=fn3}}{{small|(born 1953)}} |फेब्रुअरी १, २००६ |जनवरी ३१, २०१४ |{{age in years and days|2006|2|1|2014|1|31}} ! style="font-weight:normal" |[[जर्ज डब्लू बुस]] |- !१५ |[[File:Janet_Yellen_official_Federal_Reserve_portrait.jpg|link=https://en.wikipedia.org/wiki/File:Janet_Yellen_official_Federal_Reserve_portrait.jpg|113x113px]] |[[जेनेट एलन]]{{efn|name=fn3}}{{efn|name=fn5}}{{small|(born 1946)}} |फेब्रुअरी ३, २०१४ |फेब्रुअरी ३, २०१८ |{{age in years and days|2014|2|3|2018|2|3}} ! style="font-weight:normal" |[[बाराक ओबामा]] |- !१६ |[[चित्र:Jerome H. Powell, Federal Reserve Chair.jpg|112x112px]] |'''[[जेरोमी पावेल]]'''{{efn|name=fn3}}{{small|(born 1953)}} |फेब्रुअरी ५, २०१८ |Incumbent |{{age in years and days|2018|2|5}} ! style="font-weight:normal" |[[डोनाल्ड ट्रम्प]]<br>[[जो बाइडेन]] |} ==यो पनि हेर्नुहोस्== * [[युरोपेली केन्द्रीय बैङ्कका प्रमुख|केन्द्रीय युरोपेली बैंकका प्रमुख]] ==सन्दर्भ सामग्री== {{reflist}} ==नोट== {{notelist}} ==बाह्य कडीहरू== *[http://www.federalreserve.gov/aboutthefed/default.htm आधिकारिक वेबसाइट] [[श्रेणी:अमेरिकी केन्द्रीय बैङ्कका अध्यक्षहरू]] b2wjvgjndw7elxqxye5eqs0bx86ift4 1361168 1361164 2026-06-11T13:59:10Z Bishaldev100 28807 /* */ 1361168 wikitext text/x-wiki {{Infobox official post | post = अध्यक्ष | body = अमेरिकी केन्द्रीय बैङ्क प्रणालीको गवर्नरहरूको समिति | flag = Flag_of_the_United_States_Federal_Reserve.svg | flagcaption = [[अमेरिकी केन्द्रीय बैङ्क प्रणाली]]को झण्डा | insignia = Seal of the United States Federal Reserve Board.svg | insigniacaption = [[अमेरिकी केन्द्रीय बैङ्क प्रणाली|अमेरिकी केन्द्रीय बैङ्क प्रणालीको गवर्नरहरू]]को छाप | image = 2026 Kevin Warsh at the White House on May 22 (cropped).jpg | incumbent = [[केभिन वार्स]] | incumbentsince = सन् २०२६ मे २२ | appointer = [[अमेरिकाका राष्ट्रपतिह‍रूको सूची|अमेरिकाका राष्ट्रपति]] | formation = सन् १९१४ अगस्त १० | first = [[चार्ल्स सम्नर ह्याम्लिन]] | salary = $२,०१,७००<ref>http://www.federalreserve.gov/faqs/about_12591.htm</ref> (2014) | website = [http://www.federalreserve.gov/aboutthefed/bios/board/yellen.htm वेब] }} '''अमेरिकी केन्द्रीय बैङ्क प्रणालीको गवर्नरहरूको अध्यक्ष''' [[संयुक्त राज्य अमेरिका|अमेरिका]] [[केन्द्रीय बैङ्क|केन्द्रीय बैङ्क प्रणाली]]को [[फेडरल रिजर्भ]]को प्रमुख हुन्छ। सामन्य बोलचालको भाषमा यसको प्रमुखलाई "फेडको अध्यक्ष", "फेड अध्यक्ष" तथा "फेड प्रमुख" पनि भन्ने गरिन्छ। यस प्रणालीको [[अध्यक्ष (कर्मचारी))|अध्यक्ष]] [[अमेरिकी केन्द्रीय बैङ्क प्रणाली|अमेरिकी केन्द्रीय बैङ्क प्रणालीको गवर्नरहरू]]को "सक्रिय कार्यकारी कर्मचारी" हुन्छ।<ref>see {{usc|12|242}}</ref> हाल यसको प्रमुख केभिन वार्स हुन्। ==सन् १९३५ को पुनर्गठन== {{ठुटो}} ==नियुक्ति प्रक्रिया== ==अमेरिकी केन्द्रीय बैङ्कको अध्यक्षहरूको सूची== फेडरल रिजर्भको बोर्ड अफ गभर्नरको अध्यक्षहरूको सूची निम्नानुसार छ। अध्यक्षको कार्यकाल चार वर्षको हुन्छ, तर निरन्तर कयौं चार वर्षको लागि पुनर्नियुक्त हुन सक्छन्। सन् १९१४ मा फेडरल रिजर्भको स्थापना भएपछिका अध्यक्षहरू।{{efn|अध्यक्षलाई सुरुवातमा १९३५ अगस्ट २३ सम्म "गभर्नर" भनिन्थ्यो र त्यसपछि "अध्यक्ष " भन्न थालियो।}}<ref name="Chairs">{{cite web |title = Chairs |work = Membership of the Board of Governors of the Federal Reserve System, 1914–present |publisher = The Federal Reserve Board |date = February 5, 2018 |url=http://www.federalreserve.gov/aboutthefed/bios/board/boardmembership.htm |access-date = February 6, 2018}}</ref> {| class="wikitable" style="text-align:center" ! rowspan="2" |{{No.}} ! rowspan="2" |चित्र ! rowspan="2" |नाम<br />{{small|(birth–death)}} ! colspan="2" |Term of office ! rowspan="2" |पदावधि ! rowspan="2" |First appointed by |- !कार्यकाल सुरु !कार्यकाल अन्त्य |- !- |[[File:William-gibbs-mcadoo-desk.jpg|link=https://en.wikipedia.org/wiki/File:William-gibbs-mcadoo-desk.jpg|122x122px]] |'''[[:en:William_Gibbs_McAdoo|{{efn|name=fn1}}]]''' '''[[:en:William_Gibbs_McAdoo|विलियम गिब्स म्याक अडु]]'''{{efn|name=fn1}} {{small|(1863–1941)}} |December २३, १९१३ |अगस्ट १०, १९१४ |{{age in years and days|1913|12|23|1914|8|10}} ! style="font-weight:normal" |''[[:en:Ex_officio_member|पदेन सदस्य]]'' |- !१ |[[File:HAMLIN,_CHARLES_S._ASSISTANT_SECRETARY_OF_THE_TREASURY,_1913-_LCCN2016864808_(cropped).jpg|link=https://en.wikipedia.org/wiki/File:HAMLIN,_CHARLES_S._ASSISTANT_SECRETARY_OF_THE_TREASURY,_1913-_LCCN2016864808_(cropped).jpg|124x124px]] |'''[[:en:Charles_Sumner_Hamlin|चार्ल्स समनर ह्यामलिन]]'''{{efn|name=fn2}}{{small|(1861–1938)}} |अगस्ट १०, १९१४ |अगस्ट ९, १९१६ |{{age in years and days|1914|8|10|1916|8|9}} ! rowspan="2" style="font-weight:normal" |[[:en:Woodrow_Wilson|Woodrow Wilson]] |- !२ |[[File:William_P.G._Harding.jpg|link=https://en.wikipedia.org/wiki/File:William_P.G._Harding.jpg|120x120px]] |'''[[:en:William_P._G._Harding|विलियम पी.जी. हार्डिङ]]'''{{efn|name=fn3}}{{small|(1864–1930)}} |अगस्ट १०, १९१६ |अगस्ट ९, १९२२ |{{age in years and days|1916|8|10|1922|8|9}} |- !३ |[[File:Daniel_R._Crissinger_cropped.jpg|link=https://en.wikipedia.org/wiki/File:Daniel_R._Crissinger_cropped.jpg|122x122px]] |'''[[:en:Daniel_Richard_Crissinger|डेनियल रिचार्ड क्रिसिन्जर]]''' {{efn|name=fn4}}{{small|(1860–1942)}} |May १, १९२३ |September १५, १९२७ |{{age in years and days|1923|5|1|1927|9|15}} ! style="font-weight:normal" |[[:en:Warren_G._Harding|Warren G. Harding]] |- !४ |[[File:Chair_Roy_A_Young_140501.jpg|link=https://en.wikipedia.org/wiki/File:Chair_Roy_A_Young_140501.jpg|118x118px]] |'''[[:en:Roy_A._Young|रोय ए. योङ]]'''{{small|(1882–1960)}} |अक्टोबर ४, १९२७ |अगस्ट ३१, १९३० |{{age in years and days|1927|10|4|1930|8|31}} ! style="font-weight:normal" |[[:en:Calvin_Coolidge|Calvin Coolidge]] |- !५ |[[File:Portrait_of_Eugene_Meyer.jpg|link=https://en.wikipedia.org/wiki/File:Portrait_of_Eugene_Meyer.jpg|120x120px]] |'''[[:en:Eugene_Meyer_(financier)|इउजिन मेएर]]''' {{small|(1875–1959)}} |September १६, १९३० |May १०, १९३३ |{{age in years and days|1930|9|16|1933|5|10}} ! style="font-weight:normal" |[[हर्बर्ट हुबर]] |- !६ |[[File:Eugene_R_Black_1934_(cropped).jpg|link=https://en.wikipedia.org/wiki/File:Eugene_R_Black_1934_(cropped).jpg|111x111px]] |'''[[:en:Eugene_Robert_Black|इउजिन रोबर्ट ब्ल्याक]]'''{{small|(1873–1934)}} |May १९, १९३३ |अगस्ट १५, १९३४ |{{age in years and days|1933|5|19|1934|8|15}} ! rowspan="2" style="font-weight:normal" |[[फ्र्याङ्क्लिन डी. रुजबेल्ट]] |- !७ |[[File:Marriner_Eccles_(cropped).jpg|link=https://en.wikipedia.org/wiki/File:Marriner_Eccles_(cropped).jpg|117x117px]] |'''[[:en:Marriner_S._Eccles|मारिनर एस. एक्लेस]]''' {{efn|name=fn2}}{{small|(1890–1977)}} |November १५, १९३४ |जनवरी ३१, १९४८{{efn|Served as ''chairman pro tempore'' from February 3, 1948 to April 15, 1948.}} |{{age in years and days|1934|11|15|1948|1|31}} |- !८ |[[File:00035_DUP_(14083184875).jpg|link=https://en.wikipedia.org/wiki/File:00035_DUP_(14083184875).jpg|132x132px]] |'''[[:en:Thomas_B._McCabe|थोमस बि. म्याक केब]]'''{{small|(1893–1982)}} |April १५, १९४८ |मार्च ३१, १९५१ |{{age in years and days|1948|4|15|1951|3|31}} ! rowspan="2" style="font-weight:normal" |[[ह्यारी एस ट्रुम्यान]] |- !९ |[[File:William_McChesney_Martin_jr.jpg|link=https://en.wikipedia.org/wiki/File:William_McChesney_Martin_jr.jpg|127x127px]] |'''[[:en:William_McChesney_Martin|विलियम म्याकचेस्नी मार्टिन]]''' {{small|(1906–1998)}} |April २, १९५१ |जनवरी ३१, १९७० |{{age in years and days|1951|4|2|1970|1|31}} |- !१० |[[File:ArthurBurns_USArmyPhoto_1955.jpg|link=https://en.wikipedia.org/wiki/File:ArthurBurns_USArmyPhoto_1955.jpg|105x105px]] |'''[[:en:Arthur_F._Burns|आर्थर एफ. बर्न्स]]''' {{small|(1904–1987)}} |फेब्रुअरी १, १९७० |जनवरी ३१, १९७८{{efn|Served as ''chairman pro tempore'' from February 1, 1978 to March 7, 1978, and remained a member of the Board until March 31, 1978.}} |{{age in years and days|1970|2|1|1978|1|31}} ! style="font-weight:normal" |[[रिचार्ड निक्सन]] |- !११ |[[File:G._William_Miller.jpg|link=https://en.wikipedia.org/wiki/File:G._William_Miller.jpg|106x106px]] |'''[[:en:G._William_Miller|जि. विलियम मिलर]]''' {{small|(1925–2006)}} |मार्च ८, १९७८ |अगस्ट ६, १९७९ |{{age in years and days|1978|3|8|1979|8|6}} ! rowspan="2" style="font-weight:normal" |[[जिम्मी कार्टर]] |- !१२ |[[File:Paulvolcker.jpg|link=https://en.wikipedia.org/wiki/File:Paulvolcker.jpg|117x117px]] |'''[[:en:Paul_Volcker|पल भोलकर]]'''{{small|(1927–2019)}} |अगस्ट ६, १९७९ |अगस्ट ११, १९८७ |{{age in years and days|1979|8|6|1987|8|11}} |- !१३ |[[File:Alan_Greenspan_color_photo_portrait.jpg|link=https://en.wikipedia.org/wiki/File:Alan_Greenspan_color_photo_portrait.jpg|119x119px]] |'''[[:en:Alan_Greenspan|एलन ग्रिनस्प्यान]]'''{{small|(born 1926)}} |अगस्ट ११, १९८७ |जनवरी ३१, २००६{{efn|Served as ''chairman pro tempore'' from March 3, 1996 to June 20, 1996, while awaiting confirmation by the United States Senate for his third term as chairman.}} |{{age in years and days|1987|8|11|2006|1|31}} ! style="font-weight:normal" |[[रोनाल्ड रेगन]] |- !१४ |[[File:Ben_Bernanke_official_portrait.jpg|link=https://en.wikipedia.org/wiki/File:Ben_Bernanke_official_portrait.jpg|113x113px]] |[[बेन बर्नान्की]]{{efn|name=fn3}}{{small|(born 1953)}} |फेब्रुअरी १, २००६ |जनवरी ३१, २०१४ |{{age in years and days|2006|2|1|2014|1|31}} ! style="font-weight:normal" |[[जर्ज डब्लू बुस]] |- !१५ |[[File:Janet_Yellen_official_Federal_Reserve_portrait.jpg|link=https://en.wikipedia.org/wiki/File:Janet_Yellen_official_Federal_Reserve_portrait.jpg|113x113px]] |[[जेनेट एलन]]{{efn|name=fn3}}{{efn|name=fn5}}{{small|(born 1946)}} |फेब्रुअरी ३, २०१४ |फेब्रुअरी ३, २०१८ |{{age in years and days|2014|2|3|2018|2|3}} ! style="font-weight:normal" |[[बाराक ओबामा]] |- !१६ |[[चित्र:Jerome H. Powell, Federal Reserve Chair.jpg|112x112px]] |'''[[जेरोमी पावेल]]'''{{efn|name=fn3}}{{small|(born 1953)}} |फेब्रुअरी ५, २०१८ |Incumbent |{{age in years and days|2018|2|5}} ! style="font-weight:normal" |[[डोनाल्ड ट्रम्प]]<br>[[जो बाइडेन]] |} ==यो पनि हेर्नुहोस्== * [[युरोपेली केन्द्रीय बैङ्कका प्रमुख|केन्द्रीय युरोपेली बैंकका प्रमुख]] ==सन्दर्भ सामग्री== {{reflist}} ==नोट== {{notelist}} ==बाह्य कडीहरू== *[http://www.federalreserve.gov/aboutthefed/default.htm आधिकारिक वेबसाइट] [[श्रेणी:अमेरिकी केन्द्रीय बैङ्कका अध्यक्षहरू]] 5iz6r56pln2pqz5g1olu7uuh4fdltwf लेफ्टिनेन्ट 0 73606 1361172 1259616 2026-06-11T14:14:33Z Bishaldev100 28807 /* */ 1361172 wikitext text/x-wiki '''लेफ्टिनेन्ट वा लुटेनेन्ट''' ({{IPAc-en|uk|l|E|f|'|t|E|n|@n|t}} {{Respell|lef|TEN|ənt}} or {{IPAc-en|us|l|u:|'|t|E|n|@n|t}} {{Respell|loo|TEN|ənt}}<ref>{{cite book|last=Wells|first=John|authorlink=John C. Wells|title=Longman Pronunciation Dictionary|publisher=Pearson Longman|edition=3rd|date=3 April 2008|isbn=978-1-4058-8118-0}}</ref> 'लेफ्टिनेन्ट') वा आम बोलिचालीमा '''लप्टन''' [[सेना|सशस्त्र बल]], [[वारुणयन्त्र शाखा]], [[प्रहरी]] र कयौं देशको सङ्घ र सङ्गठनको सबैभन्दा दोस्रो कनिष्ठ वा सबैभन्दा कनिष्ठ दर्जा हो। लेफ्टिनेन्टको अर्थ विभिन्न सेनामा फरक फरक हुन्छ, तर प्रायजसो यसलाई वरिष्ठ ([[प्रथम लेफ्टिनेन्ट]]) र जुनियर ([[सेकेन्ड लेफ्टिनेन्ट]] र केही अवस्थामा तेस्रो लेफ्टिनेन्ट) पद क्रममा समेत विभाजित गरिएको हुन्छ। [[नौसेना]]मा यो प्राय [[क्याप्टेन (नौसेना)|क्याप्टेन]]को पद क्रमको बराबर हुन्छ। यो पदको उपयोग [[वारुणयन्त्र शाखा|अग्निनियन्त्रक सेवा]], आपातकालीन चिकित्सा सेवा, सुरक्षा सेवा र प्रहरी बलमा गर्ने गरिएको छ। ==नेपाली सेना== {{Main|नेपाली सेना}} [[File:12.Nepalese Army-1LT.svg|150px|center|नेपाली सेनाको उपसेनानी पदको दर्जा चिह्न]] नेपाली सेनामा उपसेनानी अधिकृत सरहको अधिकारी हुन्छन्।<ref>{{Cite web |url=http://annapurnapost.com/news/123413 |title=मर्यादाक्रममा सेनाको आपत्ति |website=अन्नपूर्ण पोस्ट |language=नेपाली |accessdate=2020-08-31}}</ref><ref>{{Cite web |url=https://www.bbc.com/nepali/news/2013/04/130428_army_integration |title='लडाकू उपसेनानीबाट केही महिनामै कर्णेल' |date=2013-04-28 |website=बिबिसी नेपाली |language=नेपाली |accessdate=2020-08-31}}</ref> ==सन्दर्भ सामग्रीहरू== {{reflist}} {{कमन्सश्रेणी|Lieutenants}} [[श्रेणी:सेनाको पद-संरचना]] 7l5i21q615gbhzj47dw6gunm10pc1lu नेमरुत डग 0 78740 1361484 1159757 2026-06-12T11:00:42Z Janak Bhatta 10885 /* बाह्य कडीहरू */ ठुटो लेख 1361484 wikitext text/x-wiki {{Infobox World Heritage Site | WHS = माउन्ट नेमरुत | Image = [[File:Nemrut Mountain Peak.JPG|250px|The man-made peak of Mount Nemrut with statues of gods and the assumed tomb of King Antiochus Theos of Commagene]] | State Party = टर्की | Type = सांस्कृतिक | Criteria = i, iii, iv | ID = ४४८ | Region = [[युरोपको विश्व सम्पदा क्षेत्रहरूको सूची|युरोप र एसिया]] | Year = १९८७ | Session = ११औं | Link = http://whc.unesco.org/en/list/448 | map_width = 250 | locmapin = टर्की | relief = 1 | latitude = 37.9816 | longitude = 38.7411 }} '''नेमरुत''' ({{lang-tr|Nemrut Dağı}} ; {{lang-hy|Նեմրութ լեռ}})टर्कीमा रहेको विश्व सम्पदा क्षेत्र हो । ==इतिहास== {{ठुटो}} ==चित्र दिर्घा== <gallery> File:Mount Nemrut (1).JPG File:Mount Nemrut (3).JPG File:Mount Nemrut (4).jpg File:Heads on Mount Nemrut.JPG File:Mount Nemrut 1.jpg File:Mount Nemrut - East Terrace (4961323529).jpg File:East Terrace (4961356591).jpg File:West Terrace (4961375519).jpg File:NemrudOstThrone.jpg File:Mount Nemrut - Apollo and Heracles Artagnes Ares (4961939940).jpg File:Mount Nemrut - Antiochus (4962117788).jpg File:Mount Nemrut - Apollo (4961945512).jpg File:Zeus Oromasdes (4961550509).jpg File:Heracles Artagnes Ares (4961567803).jpg File:Goddess of Kommagene (Tyche) (4961562037).jpg File:NemrudWestAdlerkopf.jpg File:Aslan (Lion) (4961933152).jpg File:Eagle and Lion (4962096376).jpg File:Nemrut Dagi (3823873001).jpg </gallery> ==सन्दर्भ सामग्रीहरू== {{reflist}} ==बाह्य कडीहरू== {{ठुटो}} {{commonscat|Mount Nemrut|माउन्ट नेमरुत}} {{विश्व सम्पदा क्षेत्रहरूको सूची}} {{एसियाका विश्व सम्पदा क्षेत्रहरूको सूची}} {{युरोपका विश्व सम्पदा क्षेत्रहरूको सूची}} [[श्रेणी:विश्वसम्पदाथन २०१५ मा बनाइएका वा सुधारिएका लेखहरू]] [[श्रेणी:टर्कीका विश्व सम्पदा क्षेत्रहरू]] bpwrhvquq7uktj8tioy81tmm2ulwgd4 नेपालको संविधान २०७२ 0 79959 1361191 1356351 2026-06-12T05:26:53Z Bishaldev100 28807 1361191 wikitext text/x-wiki {{Featured article}} {{Infobox document | document_name= नेपालको संविधान २०७२ | italic_title= no | image=Constitution of Nepal.jpg | image_width= | image_caption= नेपालको संविधान २०७२ | date_created= २०७२ असोज १ गते | date_ratified= २०७२ असोज ३ गते | location_of_document= नेपाल कानुन किताव व्यवस्था समिति | writer= संविधानसभाका सदस्य | हस्ताक्षरकर्ता= ६०१ मध्ये ५४१ सदस्यहरूले पारित गरेपछि सभाध्यक्ष द्वारा प्रमाणित गरी राष्ट्रपतिद्वारा जारी गरिएको। | purpose= नेपालको अन्तरिम संविधान २०६३ लाई प्रतिस्थापन गर्न | wikisource= }} {{ढाँचा:नेपालको संविधान २०७२}} '''नेपालको संविधान २०७२''' नेपालको विद्यमान संविधान हो। यो नेपालको तत्कालीन 'संविधान सभा'ले बनाएको हो। यो जनताका प्रतिनिधिले पारित गरेको पहिलो र नेपालको सातौँ संविधान हो। संविधान सभाको दोश्रो निर्वाचनबाट निर्वाचित संविधान सभाले २०७२ साल भदौ ३० गते यो संविधान दुई-तिहाई भन्दा बढी मतले पारित गरेको हो। साथै नेपालकै इतिहासमा जनता माझ गएर मस्यौदा तयार गरिएको यो पहिलो र विश्वको सबैभन्दा पछिल्लो संविधान हो। नेपालको तराई क्षेत्रका जिल्लाहरूमा यस विरुद्ध आवाज उठाइएता पनि गणक पूरक संख्या पुराएर यो संविधान दुइतिहाई (नब्बे प्रतिशतभन्दा बढीको) बहुमतमा राष्ट्रपतिबाट घोषणा गरिएको हो।<ref name="कान्तिपुर">कान्तिपुर दैनिक {{cite web | url=http://kantipur.ekantipur.com/news/2015-09-16/20150916193058.html | title=पारित भयो नेपालको संविधान | accessdate=September 2015 }} {{Webarchive|url=https://web.archive.org/web/20150918002748/http://kantipur.ekantipur.com/news/2015-09-16/20150916193058.html |date=2015-09-18 }}</ref><ref name="सेतोपाटी">सेतोपाटी अनलाइन {{cite web | url=http://setopati.com/raajneeti/33955/ | title=नेपालको संविधान दुई तिहाइ बहुमतद्वारा पारित | accessdate=September 2015 }} {{Webarchive|url=https://web.archive.org/web/20150918224125/http://setopati.com/raajneeti/33955 |date=2015-09-18 }}</ref><ref name="अन्नपूर्ण पोष्ट">अन्नपूर्ण पोष्ट दैनिक {{cite web | url=http://annapurnapost.com/News.aspx/story/19236 | title=नेपालको नयाँ संविधान अत्यधिक बहुमतले पारित | accessdate=September 2015 }} {{Webarchive|url=https://web.archive.org/web/20150919204551/http://www.annapurnapost.com/News.aspx/story/19236 |date=2015-09-19 }}</ref> यो संविधान २०७२ असोज १ गते संविधानसभाका बहुमत सदस्यहरूबाट हस्ताक्षर भएपछि सभाध्यक्षबाट प्रमाणित गरिएको थियो। तराईको जिल्लाहरूमा कालोदिन भनि विरोध भएतापनि संविधान २०७२ असोज ३ गते नेपालका राष्ट्रपति [[रामवरण यादव]]ले नेपालको संविधान २०७२ मा हस्ताक्षर गर्दै संविधान जारी भएको घोषणा गरी लागू गरिएको हो।<ref name="bbcnepal">बिबिसि नेपाली सेवा{{cite web | url=http://www.bbc.com/nepali/news/2015/09/150920_new_constitution | title=राष्ट्रपतिद्वारा संविधान जारी भएको घोषणा| accessdate= 20 September 2015}}</ref> यस संविधानमा ३५ भाग ३०८ वटा धारा र ९ वटा अनुसूचीहरू रहेका छन्। संविधानले नेपाललाई धर्म निरपेक्ष राष्ट्र घोषणा गर्नुका साथै पहिलो पटक संघीय मुलुकको रुपमा स्थापित गरेको छ । ==प्रस्तावना== <blockquote>नेपालको संविधानको प्रस्तावनामा निम्नानुसार उल्लेख गरिएको छः नेपालीमा:<ref>{{Cite web|last=नेपाल कानून आयोग|title=नेपालको संविधान|url=https://www.lawcommission.gov.np/np/?p=1547&amp|url-status=live|access-date=8 January 2022|website=नेपाल कानून आयोग|archive-url=https://web.archive.org/web/20220108021901/https://www.lawcommission.gov.np/np/?p=1547&amp |archive-date=January 8, 2022 }}</ref> " ''हामी सार्वभौमसत्तासम्पन्न नेपाली जनता;'' ''नेपालको स्वतन्त्रता, सार्वभौमिकता, भौगोलिक अखण्डता, राष्ट्रिय एकता, स्वाधीनता र स्वाभिमानलाई अक्षुण्ण राखी जनताको सार्वभौम अधिकार, स्वायत्तता र स्वशासनको अधिकारलाई आत्मसात् गर्दै;'' ''राष्ट्रहित, लोकतन्त्र र अग्रगामी परिवर्तनका लागि नेपाली जनताले पटक– पटक गर्दै आएका ऐतिहासिक जन आन्दोलन, सशस्त्र संघर्ष, त्याग र बलिदानको गौरवपूर्ण इतिहासलाई स्मरण एवं शहीदहरू तथा बेपत्ता र पीडित नागरिकहरूलाई सम्मान गर्दै;'' ''सामन्ती, निरंकुश, केन्द्रीकृत र एकात्मक राज्यव्यवस्थाले सृजना गरेका सबै प्रकारका विभेद र उत्पीडनको अन्त्य गर्दै;'' ''बहुजातीय, बहुभाषिक, बहुधार्मिक, बहुसांस्कृतिक तथा भौगोलिक विविधतायुक्त विशेषतालाई आत्मसात् गरी विविधताबीचको एकता, सामाजिक सांस्कृतिक ऐक्यबद्धता, सहिष्णुता र सद्भावलाई संरक्षण एवं प्रवर्धन गर्दै; वर्गीय, जातीय, क्षेत्रीय, भाषिक, धार्मिक, लैंगिक विभेद र सबै प्रकारका जातीय छुवाछूतको अन्त्य गरी आर्थिक समानता, समृद्धि र सामाजिक न्याय सुनिश्चित गर्न समानुपातिक समावेशी र सहभागितामूलक सिद्धान्तका आधारमा समतामूलक समाजको निर्माण गर्ने संकल्प गर्दै;'' ''जनताको प्रतिस्पर्धात्मक बहुदलीय लोकतान्त्रिक शासन प्रणाली, नागरिक स्वतन्त्रता, मौलिक अधिकार, मानव अधिकार, बालिग मताधिकार, आवधिक निर्वाचन, पूर्ण प्रेस स्वतन्त्रता तथा स्वतन्त्र, निष्पक्ष र सक्षम न्यायपालिका र कानूनी राज्यको अवधारणा लगायतका लोकतान्त्रिक मूल्य र मान्यतामा आधारित समाजवादप्रति प्रतिबद्ध रही समृद्ध राष्ट्र निर्माण गर्न;'' ''सङ्घीय लोकतान्त्रिक गणतन्त्रात्मक शासन व्यवस्थाको माध्यमद्वारा दिगो शान्ति, सुशासन, विकास र समृद्धिको आकांक्षा पूरा गर्न संविधान सभाबाट पारित गरी यो संविधान जारी गर्दछौँ''। "</blockquote> == संविधानका भागहरू== ===भाग–१ प्रारम्भिक=== (१) संविधान मूल कानुन<br> (२ )सर्वभौमसत्ता र राज्यकीयसत्ता <br> (३) राष्ट्र<br> (४) नेपाल राज्य<br> (५) राष्ट्रीय हित<br> (६) राष्ट्र भाषा<br> (७) सरकारी कामकाजको भाषा<br> (८) राष्ट्रीय झण्डा<br> (९) राष्ट्रीय गान इत्यादि <ref>http://parliament.gov.np/document.ph?id=24 http://parliament.gov.np/document.php?id=24 {{Webarchive|url=https://web.archive.org/web/20160307063858/http://parliament.gov.np/document.php?id=24 |date=2016-03-07 }} प्रारम्भिक</ref> ===भाग–२ [[नागरिकता|नागरिकता]]=== (१०) नागरिकताबाट बञ्चित नगरिने <br> (११) नेपाली नागरिक ठहर्ने <br> (१२) वंशीय आधार तथा लैङ्गिक पहिचान सहितको नागरिकता <br> (१३) नागरिकता प्राप्ति, पुनः प्राप्ति र समाप्ति <br> (१४) गैर आवासिय नागरिकता प्राप्त गर्न सकिने <br> (१५) नेपाली नागरिकता सम्बन्धि अन्य व्यवस्था<br> ===भाग-३ मौलिक हक र कर्तव्य=== (१६) सम्मानपुर्वक वाच्न पाउने हक <br> (१७) स्वतन्त्रताको हक <br> (१८) समानताको हक <br> (१९) सञ्चारको हक <br> (२०) न्याय सम्बन्धी हक <br> (२१) अपराध पीडितको हक<br> (२२) यातना विरूद्धको हक<br> (२३) निवारक नजरबन्द विरूद्धको हक<br> (२४) छुवाछुत र भेदभाव विरूद्धको हक<br> (२५) सम्पत्तिको हक<br> (२६) धार्मिक स्वतन्त्राको हक<br> (२७) सूचनाको हक<br> (२८) गोपनीयताको हक<br> (२९) शोषण विरूद्धको हक<br> (३०) स्वच्छ वातावरणको हक<br> (३१) शिक्षा सम्बन्धी हक<br> (३२) भाषा र संस्कृतिको हक<br> (३३) रोजगारको हक<br> (३४) श्रमको हक<br> (३५) स्वास्थ्य सम्बन्धी हक<br> (३६) खाद्य सम्बन्धी हक<br> (३७) आवासको हक<br> (३८) महिलाको हक<br> (३९) बालबालिकाको हक (४०) दलितको हक<br> (४१) ज्येष्ठ नागरिकको हक<br> (४२ )सामाजिक न्यायको हक<br> (४३) सामाजिक सुरक्षाको हक<br> (४४) उपभोक्ताको हक<br> (४५) देश निकाला विरुद्धको हक<br> (४६) संबैधानिक उपचारको हक<br> (४७) मौलिक हकको कार्यन्यायन<br> (४८) नागरिकका कर्तब्य ===भाग–४ राज्यका निर्देशक सिद्धान्त, नीति तथा दायित्व === (५०) निर्देशक सिद्धान्त <br>(५१) राज्यका नीतिहरू<br>(५२) राज्यको दायित्व<br>(५३) प्रतिवेदन पेश गर्ने<br>(५४) अनुगमन सम्बन्धी व्यवस्था<br>(५५) अदालतमा प्रश्न उठाउन नसकिने ===भाग–५ राज्यको संरचना र राज्य शक्तिको बाँडफाँड=== (५६) राज्यको संरचना<br>(५७) राज्य शक्तिको बाँडफाँड<br>(५८) अविशिष्ट अधिकार<br>(५९) आर्थिक अधिकारको प्रयोग<br>(६०) राजश्व स्रोतको बाँडफाँड ===भाग–६ राष्ट्रपति र उपराष्ट्रपति=== (६१) राष्ट्रपति<br>(६२) राष्ट्रपतिको निर्वाचन<br>(६३) राष्ट्रपतिको पदावधि<br>(६४) राष्ट्रपतिको योग्यता<br>(६५) राष्ट्रपतिको पद रिक्त हुने अवस्था<br>(६६) राष्ट्रपतिको काम, कर्तव्य र अधिकार<br>(६७) उपराष्ट्रपति<br>(६८) उपराष्ट्रपतिको पद रिक्त हुने अवस्था<br>(६९) उपराष्ट्रपति सम्बन्धी अन्य व्यवस्था<br>(७०) राष्ट्रपति र उपराष्ट्रपति फरक फरक लिङ्ग वा समुदायको हुने<br>(७१) राष्ट्रपति र उपराष्ट्रपतिको सपथ<br>(७२) राष्ट्रपति र उपराष्ट्रपतिको पारिश्रमिक तथा सुबिधा<br>(७३) राष्ट्रपति र उपराष्ट्रपतिको कार्यालय ===भाग–७ सङ्घीय कार्यपालिका=== (७४) शासकीय स्वरूप<br> (७५) कार्यकरणी अधिकार <br> (७६) मन्त्रीपरिषद गठन <br> (७७) प्रधानमन्त्री तथा मन्त्रीपरिषद रिक्त हुने अवस्था <br> (७८) सङ्घीय संसदको सदस्य नभाको व्यक्ति मन्त्री हुने <br> (७९) प्रधानमन्त्री र मन्त्रीको पारि श्रमिक तथा अन्य सुविधा <br> (८०) शपथ <br> (८१) राष्ट्रपतिलाई जानकारी दिन <br> (८२) नेपाल सस्कारको कार्य सञ्चालन ===भाग - ८ सङ्घीय व्यवस्थापिका=== (८३) सङ्घीय व्यवस्थापिका <br> (८४) प्रतिनिधि सभाको गठन <br> (८५) प्रतिनिधि सभाको कार्यकाल <br> (८६) राष्ट्रीय सभा को गठन र सदस्यहरूको पदावधि <br> (८७) सदस्यको लागि योग्यता <br> (८८) शपथ <br> (८९) स्थानको रिक्तता <br> (९०) सदस्यताको लागि अयोग्यता सम्बन्धी निर्णय <br> (९१) प्रतिनिधि सभाको सभामुख र उपसभामुख <br> (९२) राष्ट्रीय सभाको अध्यक्ष र उपाघ्यक्ष <br> (९३) अधिवेशन आहवन र अन्त्य <br> (९४) गण पूरक संख्या <br> (९५) राष्ट्रपतिबाट सम्बोधन <br> (९६) उपप्रधानमन्त्री, प्रधानमन्त्री, राज्य मंत्री र सहायक मन्त्रीले दुबै बैठकमा भाग लिन पाउने <br> (९७) समितिको गठन <br> (९८) सदस्यको स्थान रिक्त रहेको अवस्थामा सदनको कार्य सञ्चालन <br> (९९) मतदान <br> (१००) बिस्वासको मत र अबिस्वाशको प्रस्ताब सम्बन्धी व्यवस्था <br> (१०१)महाअभियोग <br> (१०२) अनधिकार उपस्थित भएमा वा मतदान गरेमा सजाय <br> (१०३) विशेषाधिकार <br> (१०४) कार्य सञ्चालन बिधि <br> (१०५) बहसमा बन्देज <br> (१०६) सङ्घीय संसधको महासचिब र सचिब <br> (१०७) सङ्घीय संसदको सचिबालय <br> (१०८) पारिश्रमिक ===भाग–९ सङ्घीय व्यवस्थापन कार्यविधि=== (१०९) सङ्घीय संसदको व्यवस्थापिकीय अधिकार <br> (११०) बिधेयक प्रस्तुत गर्ने बिधि <br> (१११) बिधेयक पारित गर्ने बिधि <br> (११२) बिधेयक फिरता लिने <br> (११३) बिधेयकमा प्रमाणीकरण <br> (११४) अध्यादेश ===भाग–१० सङ्घीय आर्थिक कार्यप्रणालि=== (११५) कर लगाउन वा ऋण लीन नपाउने<br> (११६) सङ्घीय संचित कोष <br> (११७) सङ्घीय संचित कोष वा सङ्घीय सरकारी कोषबाट व्यय <br> (११८) सङ्घीय संचित कोषमाथि व्ययभार <br> (११९) राजस्व र व्ययको अनुमान <br> (१२०) बिनियोजन ऐन <br> (१२१) पूरक अनुमान <br> (१२२) पेस्कि खर्च <br> (१२३) उधारो खर्च <br> (१२४) सङ्घीय आकस्मिक कोष <br> (१२५) आर्थिक कार्य बिधि सम्बन्धी ऐन ===भाग–११ न्यायपालिका=== (१२६) न्याय सम्बन्धी अधिकार अदालतबाट प्रयोग हुने<br> (१२७) अदालतहरू <br> (१२८) सर्वोच्च अदालत <br> (१२९) नेपालको प्रधान न्यायाधीस तथा सर्वोच्च अदालत्को नियुक्त र योग्यता <br> (१३०) प्रधान न्यायाधीश तथा न्यायाधीश को सेवाका सर्त र सुविधा <br> (१३१) प्रधान न्यायाधीश वा सर्वोच्च अदालत को न्यायाधीश को पद रिक्त हुने <br> (१३२) प्रधान न्यायाधीश तथा सर्वोच्च अदालत को न्यायाधीश लाइनमा अन्य कुनै काम मा लगाउन नहुने <br> (१३३) सर्वोच्च अदालत को अधिकार क्षेत्र <br> (१३४) मुद्दा सार्न सक्ने <br> (१३५) बहस,पैरवी गर्न नपाउने <br> (१३६) प्रधान न्यायाधीश को जिम्मेवारी <br> (१३७) संबैधानिक इजलास को गठन <br> (१३८) बार्षिक प्रतिबेदन <br> (१३९) उच्च अदालत <br> (१४०) उच्च अदालत का मुख्य न्यायाधीश तथा न्यायाधीश को नियुक्त्ति र योग्यता <br> (१४१) मुख्य न्यायाधीश तथा न्यायाधीश को सेवाका सर्त तथा सुबिधा <br> (१४२) मुख्य न्यायाधीश वा न्यायाधीश को पद रिक्त हुने <br> (१४३) मुख्य न्यायाधीश तथा न्यायाधीस लाई अन्य कुनै काममा लगाउन नहुने र सरुवा सम्बन्धी व्यवस्था <br> (१४४) उच्च अदालत को अधिकार क्षेत्र <br> (१४५) मुद्दा सार्न सक्ने <br> (१४६) बहस र पैरवी गर्न पाउने <br> (१४७) न्यायाधीश को जिम्मेवारी <br> (१४८) जिल्ला अदालत <br> (१४९) जिल्ला अदालत को न्यायाधीश को नियुक्ती, योग्यता तथा पारिश्रमिक र सेवाका अन्य सर्त <br> (१५०) जिल्ला न्यायाधिशलाई अन्य कुनै काममा लगाउन नहुने र सरुवा समबन्धि <br> (१५१) जिल्ला अदालतको अधिकारको क्षेत्र <br> (१५२) विशिष्टीकृत अदालत <br> (१५३) [[न्याय परिषद (नेपाल)|न्याय परिषद]] <br> (१५४) न्याय सेवा आयोग <br> (१५५) सेवाका शर्त र सुविधा सम्बन्धी व्यवस्था <br> (१५६) प्रदेश न्याय सेवा आयोग सम्बन्धी व्यवस्था ===भाग–१२ महान्यायाधिवक्ता === (१५७) महान्यायाधिवक्ता <br> (१५८) महान्यायाधिवक्ता को काम कर्तव्य र अधिकार <br> (१५९) बार्षिक प्रतिवेदन <br> (१६०) मुख्य न्यायाधिवक्ता <br> (१६१) सेवाका सर्त र सुबिधा सम्बन्धी व्यवस्था ===भाग–१३ प्रादेशिक कार्यपालिका === (१६२) प्रादेशिक कार्यकाराणी अधिकार <br (१६३) प्रदेश सम्बन्धी व्यवस्था <br> (१६४) प्रदेश प्रमुखको योग्यता <br> (१६५) प्रदेश प्रमुख्को पद रिक्त हुने अवस्था <br> (१६६) प्रदेश प्रमुखको काम,कर्तब्य र अधिकार <br> (१६७) प्रदेश प्रमुख्को शपथ <br> (१६८) प्रदेश मन्त्रीपरिषदको गठन <br> (१६९) मुख्य मन्त्री तथा मन्त्रीको पद रिक्त हुने अवस्था <br> (१७०) प्रदेश सभाको सदस्य नभएको व्यक्ति मन्त्री हुन सक्ने <br> (१७१) मुख्यमन्त्री र मन्त्रीको पारिश्रमिक र अन्य सुबिधा <br> (१७२) शपथ <br> (१७३) प्रदेश प्रमुख लाई जानकारी दिने <br> (१७४) प्रदेश सरकार को कार्य सञ्चालन ===भाग- १४ प्रदेश व्यवस्थापिका=== (१७५) प्रदेश व्यवस्थापिका<br> (१७६) प्रदेश सभा को गठन <br (१७७) प्रदेश सभाको कार्यकाल <br> (१७८) प्रदेश सभाको सदस्य का लागि योग्यता <br> (१७९) प्रदेश सभाका सदस्य को शपथ <br> (१८०) प्रदेश सभाका सदस्य को स्थान रिक्त हुने <br> (१८१) प्रदेश सभाको सदयका अयोग्यता सम्बन्धी निर्णय <br> (१८२) प्रदेश सभाको सभामुख र उपसभामुख <br> (१८३) प्रदेश सभाको अधिबेशन आव्हान र अन्त्य <br> (१८४) प्रदेश प्रमुखबाट सम्बोधन <br> (१८५) प्रदेश सभाको गुण पुरक संख्या <br> (१८६) प्रदेश सभाको मतदान <br> (१८७) प्रदेश सभाको बिषेशाधिकार <br> (१८८) विश्वासको मत र अविश्वासको प्रस्ताव सम्बन्धी व्यवस्था <br> (१८९) मन्त्री, राज्यमन्त्री र सहायक मन्त्रीले प्रदेश सभाको बैठकमा भाग लिन <br> (१९०) प्रदेश सभामा अनधिकार उपस्थित भएमा वा मतदान गरेमा सजाय <br> (१९१) बहसमा बन्देज <br> (१९२) सदस्यको स्थान रित्त रहेको अवस्थामा प्रदेश सभाको कार्य सञ्चालन <br> (१९३) प्रदेश सभाले समिति गठन गर्न सक्ने <br> (१९४) प्रदेश सभाको कार्य सञ्चालान विधि <br> (१९५) प्रदेश सभाको सचिव र सचिवालय<br> (१९६) पारिक्षमिक ===भाग–१५ प्रादेशक व्वस्थापन कार्यविधि === (१९७) प्रदेश सभाको व्यवस्थापिकीय अधिकार <br> (१९८) प्रदेश सभामा विधेयक प्रस्तुत गर्ने विधि <br> (१९९) विधेयक पारित गर्ने विधि <br> (२००) विधेयक फिर्ता लिन सक्ने <br> (२०१) विधेयकमा प्रमाणीकरण <br> (२०२) अध्यादेश <br> ===भाग–१६ प्रादेशिक आर्थिक कार्यप्रणाली === (२०३) कर लगाउन वा ऋण लिन नपाइने <br> (२०४) प्रदेश सन्चित कोष <br> (२०५) प्रदेश संचीय कोष वा प्रदेश सरकारी कोषबाट व्यय <br> (२०६) प्रदेश सन्चित कोषमाथि व्ययभार <br> (२०७) राजस्व र व्ययको अनुमान <br> (२०८) प्रदेश विनियिजन ऐन <br> (२०९) पूरक अनुमान <br> (२१०) पेश्की खर्च <br> (२११) उधारो खर्च <br> (२१२) प्रदेश आकस्मिक कोष <br> (२१३) आर्थिक कार्यविधि सम्बन्धी ऐन <br> ===भाग–१७ स्थानीय कार्यपालिका=== (२१४) स्थानीय तहको कार्यकारिणी अधिकार <br> (२१५) गाउँ कार्यपालिका अध्यक्ष र उपाध्यक्ष सम्बन्धी व्यवस्था <br> (२१६) नगर कार्यपालिका प्रमुख र उपप्रमुख सम्बन्धी व्यवस्था <br> (२१७) न्यायिक समिति <br> (२१८) गाउँ कार्यपालिका र नगर कार्यपालिकाको कार्य सञ्चालन <br> (२१९) स्थानीय तहको कार्यकारिणी सम्बन्धी अन्य व्यवस्था <br> (२२०) जिल्ला सभा र जिल्ला समन्वय समिति <br> ===भाग–१८ स्थानीय व्यवस्थापिका=== (२२१) स्थानीय तहको व्यवस्थापिकीय अधिकार <br> (२२२) गाउँ सभाको गठन <br> (२२३) नगर सभाको गठन <br> (२२४) गाउँ सभा र नगर सभाको अध्यक्ष र उपाध्यक्ष <br> (२२५) गाउँ सभा र नगर सभाको कार्यकाल <br> (२२६) कानुन बनाउन सक्ने <br> (२२७) गाउँ सभा र नगर सभा सम्बन्धी अन्य व्यवस्था <br> ===भाग–१९ स्थानीय आर्थिक कार्यप्रणाली=== (२२८) कर लगाउन वा ऋण लिन नपाइने <br> (२२९) स्थानीय सन्चित कोष <br> (२३०) गाउँपालिका र नगरपालिका राजस्व र व्ययको अनुमान <br> ===भाग–२० सङ्घ, प्रदेश र स्थानीय तह वीच अन्तरसम्बन्ध === (२३१) सङ्घ, प्रदेश बीचको व्यवस्थापिकीय अन्तरसम्बन्ध <br> (२३२) सङ्घ, प्रदेश र स्थानीय बीचको सम्बन्ध <br> (२३३) प्रदेश-प्रदेश बीचको सम्बन्ध <br> (२३४) अन्तर प्रदेश परिषद <br> (२३५) सङ्घ, प्रदेश र स्थानीय स्थानीय तह वीचको <br> (२३६) अन्तर प्रदेश व्यापार <br> (२३७) सर्वोच्च अदालतको संवैधानिक इजलासको अधिकार क्षेत्रमा असर नपर्ने <br> ===भाग–२१ अख्तियार दुरुपयोग अनुसन्धान आयोग === (२३८) अख्तियार दुरुपयोग अनुसन्धान आयोग <br> (२३९) अख्तियार दुरुपयोग अनुसन्धान आयोगको काम, कर्तव्य र अधिकार <br> ===भाग–२२ महालेखा परीक्षक === (२४०) महालेखा परीक्षक <br> (२४१) महालेखा परीक्षकको काम, कर्तव्य र अधिकार <br> ===भाग–२३ सङ्घीय लोक सेवा आयोग=== (२४२) लोक सेवा आयोग <br> (२४३) लोक सेवा आयोगको काम, कर्तव्य र अधिकार <br> (२४४) प्रदेश लोक सेवा आयोग सम्बन्धी व्यवस्था <br> ===भाग–२४ निर्वाचन आयोग === (२४५) निर्वाचन आयोग <br> (२४६) निर्वाचन आयोगको काम, कर्तव्य र अधिकार <br> (२४७) आवश्यक सहयोग गर्नु पर्ने <br> ===भाग–२५ राष्ट्रिय मानव अधिकार आयोग === (२४८) राष्ट्रिय मानव अधिकार आयोग <br> (२४९) राष्ट्रिय मानव अधिकार आयोगको काम, कर्तव्य र अधिकार ===भाग–२६ राष्ट्रिय प्राकृतिक स्रोत तथा वित्तीय आयोग === (२५०) राष्ट्रिय प्राकृतिक स्रोत तथा वित्तीय आयोग <br> (२५१) राष्ट्रिय प्राकृतिक स्रोत तथा वित्तीय आयोगको काम, कर्तव्य र अधिकार <br> ===भाग–२७ अन्य आयोगहरू === (२५२) राष्ट्रिय महिला आयोग <br> (२५३) राष्ट्रिय महिला आयोगको काम, कर्तव्य र अधिकार <br> (२५४) प्रदेशमा कार्यालय स्थापना गर्न सक्ने <br> (२५५) राष्ट्रिय दलित आयोग <br> (२५६) राष्ट्रिय दलित आयोगको काम, कर्तव्य र अधिकार <br> (२५७) प्रदेशमा कार्यालय स्थापना गर्न सक्ने <br> (२५८) राष्ट्रिय समावेशी आयोग <br> (२५९) राष्ट्रिय समावेशी आयोगको काम, कर्तव्य र अधिकार <br> (२६०) प्रदेशमा कार्यालय स्थापना गर्न सक्ने <br> (२६१) आदिवासी जनजाति आयोग <br> (२६२) मधेशी आयोग <br> (२६३) थारु आयोग <br> (२६४) मुस्लिम आयोग <br> (२६५) आयोगको पुनरावलोकन ===भाग–२८ राष्ट्रिय सुरक्षा सम्बन्धी व्यवस्था === (२६६) राष्ट्रिय सुरक्षा परिषद <br> (२६७) नेपाली सेना सम्बन्धी व्यवस्था<br> (२६८) नेपाल प्रहरी, सशस्त्र प्रहरी बल, नेपाल र राष्ट्रिय अनुसन्धान सङ्गठन सम्बन्धी व्यवस्था ===भाग–२९ राजनीतिक दल सम्बन्धी व्यवस्था === (२६९) राजनीतिक दलको गठन , दर्ता र सन्चालन <br> (२७०) राजनीतिक दललाई प्रतिबन्ध लागौं बन्देज <br> (२७१) राजनीतिक दलको रूपमा निर्वाचनका लागि मान्यता प्राप्त गर्न दर्ता गराउनु पर्ने <br> (२७२) राजनीतिक दल सम्बन्धी अन्य व्यवस्था <br> ===भाग–३० संकटकालीन अधिकार === (२७३) संकटकालीन व्यवस्था <br> ===भाग–३१ संविधान संशोधन === (२७४) संविधान संशोधन <br> ===भाग–३२ विविध === (२७५) जनमत सङ्ग्रह सम्बन्धी <br> (२७६) माफी <br> (२७७) उपाधी, समान र विभूषण <br> (२७८) सन्धि सम्पन्न गर्ने अधिकार <br> (२७९) सन्धि वा सम्झौताको अनुमोदन, सम्मिलन, स्वीकृति वा समर्थन <br> (२८०) राष्ट्रियपति कार्य गर्ने सम्बन्धी विशेष व्यवस्था <br> (२८१) विशेष अधिकारको समिक्षा तथा पुनरावलोकन <br> (२८२) राजदुत र विशेष प्रतिनिधि <br> (२८३) समावेशी सिधदान्त बमोजिम नियुक्ति गर्नु पर्ने <br> (२८४) संवैधानिक परिषद संबन्धी व्यबस्था सरकारी सेवाको गठन <br> (२८५) सरकारी सेवाको गठन (२८६) निर्वाचन क्षेत्रको निर्धारण आयोग <br> (२८७) भाषा आयोग <br> (२८८) राजधानी <br> (२८९) पदाधिकरिको नागरिकता सम्बन्धी विशेष व्यवस्था <br> (२९०) गुठि समन्धी व्यवस्था <br> (२९१) नियुक्तिका लागि योग्य नहुने <br> (२९२) संसदीय सुनुवाई सम्बन्धी व्यवस्था <br> (२९३) संवैधानिक काम कारवाहीको अनुगमन <br> (२९४) संवैधानिक निकायको वार्षिक प्रतिवेदन ===भाग–३३ संक्रमणकालीन व्यवस्था === (२९५) संधीय आयोगको गठन <br> (२९६) संविधान सभा व्यवस्थापिका-संसदमा रुपान्तरण हुने <br> (२९७) राष्ट्रपति र उपराष्ट्रपति संबन्धी व्यवस्था <br> (२९८) मन्त्रिपरिषद्को गठन सम्बन्धी व्यवस्था <br> (२९९) सभामुख र उपसभामुख सम्बन्धी व्यवस्था <br> (३००) न्यापालिका सम्बन्धी व्यवस्था <br> (३०१) संवैधानिक निकाय र पदाधिकारी संबन्धी व्यवस्था <br> (३०२) प्रदेश र स्थानीय तहमा सरकारी सेवाहरूको गठन र सञ्चालन <br> (३०३) स्थानीय निकाय संबन्धी व्यवस्था <br> (३०४) वर्तमान कानुन लागु रहने <br> (३०५)बाधा अड्काउ फुकाउने अधिकार ===भाग–३४ परिभाषा र व्याख्या === (३०६) परिभाषा र व्याख्या ===भाग–३५ संक्षिप्त नाम, प्रारम्भ र खारेजी=== (३०७) संक्षिप्त नाम र प्रारम्भ <br> (३०८) खारेजी == अनुसूची == नेपालको संविधान २०७२, मा ९ अनुसूची छन् । * [[नेपालको झन्डा|अनुसूची-१]] :[[नेपाल]]को [[राष्ट्रिय झन्डा]] * [[सयौँ थुङ्गा फूलका हामी|अनुसूची-२]]: [[सयौँ थुङ्गा फूलका हामी|नेपालको राष्ट्रिय गान]] * अनुसूची ३: [[नेपालको निसानछाप|नेपालको निशान छाप]] * [[नेपालको संविधान २०७२ को अनुसूची ४|अनुसूची ४]]: [[नेपालका प्रदेशहरू|प्रदेश र सम्बन्धित प्रदेशमा रहने जिल्लाहरू]] * अनुसूची ५ : सङ्घको अधिकारको सूची * अनुसूची ६ : प्रदेशको अधिकारको सूची * अनुसूची-७ सङ्घ र प्रदेशको साझा अधिकारको सूची * अनुसूची-८ स्थानीय तहको अधिकारको सूची * अनुसूची-९ सङ्घ, प्रदेश र स्थानीय तहको अधिकारको साझा सूची == प्रतिकृया == {{मुख्य लेख|२०७२ नेपाल नाकाबन्दी}} नयाँ सम्बिधान जारी गरेकोमा अन्तराष्ट्रिय समुदायले बधाइ सन्देश व्यक्त गरे । जापान<ref>{{Cite web |title=Japan welcomes new constitution |url=https://kathmandupost.com/national/2015/09/21/japan-welcomes-new-constitution |access-date=2026-06-12 |website=kathmandupost.com |language=English}}</ref>, चीन, युरोपेली युनियन्, अमेरिका, संयुक्त राष्ट्रसंघले बधाइ सन्देश पठाए । जापानी विदेश मन्त्रालय द्वारा जारी वक्तव्यमा नयाँ संविधान मार्फत नेपालमा राजनीतिक स्थिरता सुनिश्चित गरी प्रजातन्त्र, शान्ति निर्माण र आर्थिक विकासमा नेपालले प्रगति गर्ने आशा जापानले गरेको छ। <ref>{{Cite web |title=Adoption of the Draft of the New Constitution in Nepal (Statement by Foreign Minister Kishida) |url=https://www.mofa.go.jp/press/release/press4e_000863.html |access-date=2026-06-12 |website=Ministry of Foreign Affairs of Japan |language=en-US}}</ref> भारतले भने नेपालमा संविधान जारी भएको आफूले नोटिस गरेको बतायो। भारतले संबिधान घोषणामा केहीसाता पर्खन आग्रहको लागि आफ्ना विशेष दुतह नेपाल पठाएको थियो। सो कुराप्रति नेपाल असहमत भएर तोकिएको समयमै संबिधान घोषणा गरेको कारणका साथै नेपालको तराइको सिमाबर्ती क्षेत्रहरूमा भै रहेको तनाब र हिम्सात्मक गतिबिधी प्रमुख कारण देखाई भारतले नाकाबन्दी गर्‍यो । ==सन्दर्भ सामग्री== {{reflist}} ==यो पनि हेर्नुहोस्== * [[नेपाल सरकारको वैधानिक कानुन २००४|नेपाल सरकारको बैधानिक कानुन २००४]] * [[नेपालको अन्तरिम शासन विधान २००७]] * [[नेपाल अधिराज्यको संविधान २०१५]] * [[नेपालको संविधान २०१९]] * [[नेपाल अधिराज्यको संविधान २०४७]] * [[नेपालको जनआन्दोलन २०६३]] * [[नेपालको अन्तरिम संविधान २०६३]] * [[नेपालको संविधान को भाग-२|नेपाली नागरिकता]] *[[नेपालको संविधान २०७२ मा बालबालिकाको हक]] ==बाह्य कडीहरू== [[श्रेणी:नेपालको संविधान]] [[श्रेणी:ऐन कानुन]] [[श्रेणी:नेपालको इतिहास (२०६५–हाल)|संविधान]] [[श्रेणी:नेपालको संविधान २०७२]] iblufqkf4g04kmpcgjcnfvursmvjbzs २०७२ नेपाल नाकाबन्दी 0 80320 1361192 1238096 2026-06-12T05:28:23Z Bishaldev100 28807 1361192 wikitext text/x-wiki [[File:नेपालमा नाका बन्दीको असर 07.jpg|thumb|नेपालमा नाका बन्दीको असर]] [[File:नेपालमा नाका बन्दीको असर 05.jpg|thumb|नेपालमा नाका बन्दीको असर]] [[File:नेपालमा नाका बन्दीको असर 01.jpg|thumb|नेपालमा नाका बन्दीको असर]] '''२०७२ नेपाल नाकाबन्दी''' विसं २०७२ आश्विन ०६ गतेबाट शुरु भएको थियो। बि.सं २०७२ मा नेपालले जारी गरेको [[नेपालको संविधान २०७२|नेपालको संबिधान, २०७२]] प्रति असन्तुष्टि जनाउँदै भारतले [[नाकाबन्दी|आर्थिक नाकाबन्दी]] लगाएपछि नेपालले ठूलो [[ऊर्जा सङ्कट]]को सामना गरेको थियो। यसले नेपालको जनजीबन तथा अर्थतन्त्रमा ठुलो असर पारेको छ। नेपालको सरकारले यसलाई भारतले अघोषित रूपमा लगाएको नाकाबन्दी भनेर उल्लेख गरेता<ref>{{cite web|title=भारतले नाकाबन्दी गरेकै होः माधव नेपाल|url=http://www.onlinekhabar.com/2015/11/355170/|website=www.onlinekhabar.com|publisher=अनलाइनखबर डटकम|accessdate=२०७२ मङ्सिर १०}}</ref> पनि भारतले यस कुरालाई स्वीकार गरेको छैन ।<ref>{{cite web|title=नाकाबन्दी इन्कार गर्दै भारतले भन्यो- हामीलाई होइन, नेपाल सरकारलाई नै सोध|url=http://www.onlinekhabar.com/2015/11/352132/|website=www.onlinekhabar.com|publisher=अनलाइनखबर डटकम|accessdate=२०७२ मङ्सिर ०३}}</ref> == पृष्ठभूमि == [[File:Line of gas cylinder 2.jpg|thumb|नाकाबन्दीको कारण ग्यासको अभाव भएपछी लाइनमा रहेका ग्यास सिलिण्डरहरू]] नेपालको तराइ क्षेत्रमा संबिधान घोषणाको दिन नजिकिदै गर्दा तनाब र हिम्सात्मक गतिबिधीहरु बढ्दै गएका थिए । विशेष गरी सिमान्कन का विषयमा प्रमुख दलहरु र तराइकेन्द्रित दलहरूको बिबाद बढ्दै गैरहेको थियो ।<ref> [https://www.bbc.com/nepali/news/2015/09/150913_constitution_vote] "बीबीसी नेपाली" </ref> यही बिबादका माझ २०७२/०६/०३ संबिधानसभाबाट संबिधान जारी भयो । संबिधान जारी हुने बेलामा भारतबाट विशेष दुत पठाएर आफ्नो चासो र चिन्ता ब्यक्त गर्ने काम भयो । तराइको सीमामा सुरक्षाको कारण देखाएर मालबाहक साधनहरु विशेष गरी पेट्रोलियम पदार्थ बोकेका गाडीहरूलाई जाचपासमा कडाइ गर्ने काम सुरु भयो ।<ref> [http://www.bizmandu.com/content/-13385.html#.VlQqv7_WgqI "पाँच हजार बढी गाडी भारतीय भूमिमा अलपत्र" ], "Bizmandu" Sep 27 2015</ref> यसरी नेपालमाथि भारतले अघोशित नाकाबन्दी लगाएको हो । यसपछि सिमा सुरक्षको विषय बनाएर विश्वकै एक विशाल प्रजातान्त्रिक मुलुक [[भारत]]ले अघोषित नाक बन्दी गर्यो तर मुखमा मधेसी दललाई राख्यो। भारतले संबिधान घोषणामा केहीसाता पर्खन आग्रहको लागि आफ्ना विशेष दुतहरु नेपाल पठाएको थियो । <ref>काशीराम ढुंगाना, [http://www.ratopati.com/4696/ "स्वतन्त्र नेपाल र छिमेकी भारतको चाहना"], "रातोपाटी" </ref> सो कुराप्रति नेपाल असहमत भएर तोकिएको समयमै संबिधान घोषणा गरेको कारणका साथै नेपालको तराइको सिमाबर्ती क्षेत्रहरूमा भै रहेको तनाब र हिम्सात्मक गतिबिधी प्रमुख कारणका रूपमा रहेको पाइन्छ । हिन्दु अधिराज्यको घोषणा या धर्म निरपेक्ष शब्दको खारेजी वा नेपालको संबिधान भारतको बिहार राज्यको चुनाबपछाडी घोषणा नगरिएकोले नाकाबन्दी लगाइएको हो । <ref>धर्मेन्द्र बास्तोला, [http://onlinekhabar.com/2015/12/362309/ "संसदवादीलाई माओवादीको प्रश्न : कसरी बन्ला भारतसँग मित्रता ?"], "अनलाइनखबर"२०७२ मंसिर २८ गते १२:३०</ref> २०७२/०६/०६ गतेदेखी भारतले नेपालमा अघोशित नाकाबन्दी लगाएको हो । <ref>बुद्धिनारायण श्रेष्ठ, [http://setopati.com/blog/34571/ "पटकपटक नाकाबन्दी"] {{Webarchive|url=https://web.archive.org/web/20151002005510/http://setopati.com/blog/34571/ |date=2015-10-02 }}, ''सेतोपाटी'' बिहीबार, आश्विन १४, २०७२ ११:१९:३१</ref> ===यो पनि हेरौँ=== *नाकाबन्दीको बारेका लेख फेसबुकबाट गायब भारतीय बरिषठ पत्रकार विशाल अरोराले भारतले नेपालमाथि लगाएको नाकाबन्दी बिरुद्ध फेसबुकमा लेखेको लेख फेसबुकले सेन्सर गरेको छ । "आर आइ पि ईन्डियाज इन्फ्लुयन्स अन नेपाल" शिर्शकको सो लेख फेसबुकले सेन्सर गरेको हो । जुन लेखलाई नेपाल तथा भारतका ३००० भन्दा बढी नागरिकले सामाजिक सन्जालमा शेयर गरेका थिए ।<ref>अनलाइनखबर, [http://onlinekhabar.com/2015/11/355519/ "नाकाबन्दीबारे अरोराको लेख फेसबुकबाट 'गायब'''], "अनलाइनखबर" २०७२ मंसिर ११ गते १९:२८</ref> * [[ऊर्जा सङ्कट|उर्जा सङ्कट]] ==सन्दर्भ सामग्रीहरू== [[श्रेणी:नाकाबन्दीहरू]] 00f1aqg8vch3l20r4fden6u6msqe7zg नम्रता शिरोडकर 0 83351 1361483 1355421 2026-06-12T10:58:31Z Janak Bhatta 10885 /* जीवनी */ ठुटो लेख 1361483 wikitext text/x-wiki {{Infobox pageant titleholder | image ={{CSS image crop |Image = Guntur Kaaram Pooja ceremony.jpg |bSize = 400 |cWidth = 50 |cHeight = 200 |oTop = 30 |oLeft = 210 |Location = center }} | caption = | name = नम्रता शिरोडकर | birth_date = {{birth date|1972|01|22}} | birth_place = [[मुम्बई]], [[महाराष्ट्र ]], भारत | residence = [[फिल्म नगर]], [[हैदराबाद]], [[तेलङ्गाना]], भारत | years active = १९९३–२००४ | spouse = [[महेश बाबु]]<br/>(फेब्रुवरी २००५ – वर्त्तमान) |children =जि. गौथम कृष्ण <br>जि.सितारा | relatives = }} '''{{PAGENAME}} ''' (जन्म सन् १९७२ जनवरी २२ मुम्बई महाराष्ट्र भारत) एक भारतीय चलचित्र अभिनेत्री हुन् । उनी १९९३को मिस इन्डिया जित्न सफल भएकी थिइन् । उनले बलिउडमा आफ्नो करियरको सुरुवात 'पूरब की लैला पश्चिम की छैला'देखि गरेकी थिइन् । यस चलचित्रमा अक्षय कुमार र सुनील शेट्टीले पनि काम गरेका थिए तर केही कारणवस यो चलचित्र प्रस्तुत हुन सकेन त्यसपछि १९९८मा उनले सलमान खानको साथमा 'जब प्यार किसी से होता है' मा काम गरिन । सो चलचित्रको सफलता पछि उनी चलचित्र जीवनमा सफल भएकी थिइन ।<ref>[http://www.samaylive.com/gallery/photo-gallery/film-photogallery/pics-birthday-actress-namrata-shirodkar-turns-43/627596/112050.html samaylive.com]</ref> ==जीवनी== नम्रता शिरोडकरको जन्म सन् १९७२ जनवरी २२ मा भारतको मुम्बईमा भएको थियो । उनले आफ्नो करियरको सुरुवात मोडलिङबाट गरेकी थिइन । {{ठुटो}} ==चलचित्रहरू== ==सन्दर्भ सामग्री== {{reflist}} ==बाह्य कडीहरू== * {{IMDb name|id=0794363|name=Namrata Shirodkar}} [[श्रेणी:विकी विमिन एडिटाथन २०१६ मा बनाइएका वा सुधारिएका लेखहरू]] [[श्रेणी:भारतीय चलचित्र अभिनेत्रीहरू]] [[श्रेणी:मराठी चलचित्र अभिनेत्रीहरू]] [[श्रेणी:हिन्दी चलचित्र अभिनेत्रीहरू]] [[श्रेणी:मलयालम चलचित्र अभिनेत्रीहरू]] [[श्रेणी:कन्नड चलचित्र अभिनेत्रीहरू]] [[श्रेणी:तेलगु चलचित्र अभिनेत्रीहरू]] [[श्रेणी:फेमिना मिस इन्डिया विजेताहरू]] [[श्रेणी:जीवित मानिसहरू]] [[श्रेणी:सन् १९७२ मा जन्म]] [[श्रेणी:मुम्बईका अभिनेत्रीहरू]] [[श्रेणी:मुम्बईका महिला मोडलहरू]] f31fk2opgtb5zo5mpmqfk8rxb5innvv कानेपोखरी गाउँपालिका 0 94917 1361202 1361147 2026-06-12T06:45:05Z Prakashphuyal30 79270 1361202 wikitext text/x-wiki {{Infobox settlement <!--See the table at Infobox settlement for all fields and descriptions of usage--> <!-- आधारभूत जानकारी -->| name = | other_name = | native_name = | nickname = | settlement_type = [[गाउँपालिका]] | motto = <!-- images and maps --> | image_skyline = | image_caption = | image_flag = | image_seal = | image_map = | pushpin_label_position = bottom | pushpin_map_caption = कोशी प्रदेशको नक्सामा {{पृष्ठको नाम}}को अवस्थिति | pushpin_map = Nepal Province1#Nepal <!-- अवस्थिति--> | subdivision_type = [[देश]] | subdivision_name = {{झण्डा|नेपाल}} | subdivision_type1 = [[नेपालका प्रदेशहरू|प्रदेश]] | subdivision_name1 = [[कोशी प्रदेश]] | subdivision_type2 = [[नेपालका जिल्लाहरू|जिल्ला]] | subdivision_name2 = [[मोरङ जिल्ला|मोरङ]] |<!-- राजनीति--> | government_footnotes =<ref name="निर्वाचन २०७९">{{cite news|title=स्थानीय तह निर्वाचन २०७९|url=https://localelection2079.ekantipur.com/pradesh-1/district-morang/kanepokhari?lng=nep|accessdate=०९ साउन २०८१|language=नेपाली|publisher=कान्तिपुर दैनिक}}</ref> | government_type = | leader_title = अध्यक्ष | leader_name = राजमति इङ्गनाम <small> ([[नेपाल कम्युनिस्ट पार्टी (एकीकृत मार्क्सवादी-लेनिनवादी)|नेकपा (एमाले)]]) | leader_title1 = उपाध्यक्ष | leader_name1 = भोलाप्रसाद अधिकारी <small> ([[नेपाल कम्युनिस्ट पार्टी (एकीकृत मार्क्सवादी-लेनिनवादी)|नेकपा (एमाले)]]) | established_title = स्थापित | established_date = २७ फागुन २०७३ | unit_pref = <!--Enter: Imperial, if Imperial (metric) is desired--> | area_footnotes = | area_total_km2 = 82.83<!-- ALL fields dealing with a measurements are subject to automatic unit conversion--> |population_as_of = [[नेपालको बाह्रौँ राष्ट्रिय जनगणना, २०७८|राष्ट्रिय जनगणना २०७८]] |population_footnotes =<ref name="जनगणना २०७८">{{cite web |title=जनसङ्ख्याको आकार र वितरण|url=https://censusnepal.cbs.gov.np/results/np/population?province=1&district=12&municipality=6|accessdate=२९ जेठ २०८१|work=राष्ट्रिय जनगणना २०७८|publisher=[[राष्ट्रिय तथ्याङ्क कार्यालय (नेपाल)|राष्ट्रिय तथ्याङ्क कार्यालय]]|language=नेपाली}}</ref> | population_total = 43193 | population_density_km2 = auto | population_blank1_title = Ethnicities <!-- साधारण जानकारी -->| timezone = [[नेपालको प्रमाणिक समय|नेपाली समय]] | utc_offset = +५:४५ | timezone_DST = | utc_offset_DST = | coordinates = {{coord|26.67|87.43|type:adm2nd_region:NP_source:unmaps-enwiki|display=inline,title}} | elevation_footnotes = <!--for references: use <ref> </ref> tags--> | elevation_m = <!-- Area/postal codes & others --> | postal_code_type = | postal_code = | area_code = +९७७-०२१ | blank_name = केन्द्र | blank_info = साविक [[वयरवन]] गाविसको कार्यालय | website = [https://www.kanepokharimun.gov.np/ आधिकारिक वेबसाइट] | footnotes = }} '''{{पृष्ठको नाम}}''' [[मोरङ जिल्ला]]का ८ [[गाउँपालिका]]हरू मध्ये एक हो।<ref name="गाउँपालिका वा नगरपालिका">{{cite web|title=हेर्नुहोस्, तपाईँ कुन गाउँपालिका वा नगरपालिकामा पर्नुभयो?|url=http://setopati.com/raajneeti/64651/|publisher=सेतोपाटी|accessdate=फाल्गुन २०७३|ref=http://setopati.com/raajneeti/64651/}} {{Webarchive|url=https://web.archive.org/web/20170312170008/http://setopati.com/raajneeti/64651/ |date=2017-03-12 }}</ref> २७ फागुन २०७३ मा, गाउँपालिका घोषणा गर्दा साविकका [[वयरवन]], [[केरावन]] र [[होक्लाबारी]] [[गाउँ विकास समिति (नेपाल)|गाविस]]हरू यसमा गाभिएका थिए। ==जनसङ्ख्या== [[नेपालको बाह्रौँ राष्ट्रिय जनगणना, २०७८|राष्ट्रिय जनगणना २०७८]]को जनगणना अनुसार {{पृष्ठको नाम}}को कुल जनसङ्ख्या ४३,१९३ रहेको छ भने यहाँ १०,६६३ घरधुरी रहेका छन्।<ref name="जनगणना २०७८"/> {| class="wikitable sortable" style="text-align: center;" |+ कानेपोखरी गाउँपालिकाको वडागत तथ्याङ्क |- ! नयाँ वडा !! समावेश साविकका गाविसहरू !! जनसङ्ख्या !! क्षेत्रफल (वर्ग कि.मी.) !! जनघनत्व (व्यक्ति/वर्ग कि.मी.) |- | १ || [[होक्लाबारी]] || ५,३४८ || ११.३६ || ४७०.७७ |- | २ || [[केरावन]] (३, ४, ६–९) || ६,४९६ || १२.८ || ५०७.५० |- | ३ || [[वयरवन]] (१–५) || ५,६४८ || १०.८५ || ५२०.५५ |- | ४ || [[वयरवन]] (६, ७) || ६,४४६ || ९.८६ || ६५३.७५ |- | ५ || [[केरावन]] (१, २, ५) || ७,३५२ || १२.३६ || ५९४.८२ |- | ६ || [[वयरवन]] (८) || ६,९७४ || ६.४८ || १,०७६.२३ |- | ७ || [[वयरवन]] (९) || ४,९२९ || १८.५८ || २६५.२८ |- class="sortbottom" style="font-weight: bold; background: #f2f2f2;" | colspan="2" | '''जम्मा''' || '''४३,१९३''' || '''८२.२९''' || ५२४.८९ |} == पर्यटकीय स्थलहरु == यस क्षेत्रका प्राकृतिक तथा सांस्कृतिक पर्यटकीय स्थलहरु निम्नरहेका छन # कानेपोखरी # कालिकोशी सिमसार (मुहान) # सुन्तली चौर # भलुवा सिमसार # दहिधाप सिमसार ‌(पार्क) # ढङ्ढङ्गे मेला (धिमाल जातिको पवित्र स्थल)<ref>{{Cite web |title=Kanepokhari - Rural Municipality |url=https://edusanjal.com/local-level/kanepokhari/ |access-date=2026-06-11 |website=Edusanjal}}</ref> # किरण पोखरी -होक्लाबारी == पानीका स्रोतहरु == यस क्षेत्रमा रहेका स्थानीय पानीका स्रोतहरु निम्नरहेका छन # कालीकोशी खोला (मैदानी नदी) # भलुवा खोला (मैदानी नदी) # दहि खोला (मैदानी नदी) # ज्यामिरे खोला (मैदानी नदी) # डास खोला (चुरे-भावर नदी) # चिसाङ खोला (चुरे-भावर नदी) ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} {{मोरङ जिल्लाका स्थानीय तहहरू}} ==बाह्य कडीहरू== *[http://www.ddcmorang.gov.np/ जिल्ला विकास समितिको कार्यालय, मोरङ] {{Webarchive|url=https://web.archive.org/web/20200918064452/http://ddcmorang.gov.np/ |date=2020-09-18 }} [[श्रेणी:मोरङ जिल्लाका गाउँपालिकाहरू]] [[श्रेणी:कोशी प्रदेशका गाउँपालिकाहरू]] 1zbumjtybjrkocv2p3iwq13gyt8awd6 भर्सायको सन्धि 0 97513 1361185 1361136 2026-06-12T03:20:39Z Bishaldev100 28807 /* युद्धविराम */ 1361185 wikitext text/x-wiki [[File:Treaty of Versailles, English version.jpg|thumb|{{{image_alt}}}|alt={{{image_alt}}}|thumb|भर्सिल्स् सन्धिको बाहिरी आवरण, अङ्गरेजी संस्करण]] '''भर्सेलिजको सन्धि''' ({{lang-en|Treaty of Versailles}} {{lang-fr|Traité de Versailles}}) २८ जुन १९१९ मा हस्ताक्षर गरिएको शान्ति सन्धि थियो। [[पहिलो विश्वयुद्ध|प्रथम विश्वयुद्ध]]को सबैभन्दा महत्त्वपूर्ण सन्धिको रूपमा, यसले जर्मनी र अधिकांश मित्र राष्ट्रहरू बीचको युद्धको अवस्थाको अन्त्य गर्‍यो। आर्कड्यूक फ्रान्ज फर्डिनान्डको हत्या (उक्त घटना विश्व युद्धको कारण )को ठीक पाँच वर्ष पछि भर्साइलको दरबारमा हस्ताक्षर गरिएको थियो, जसले युद्ध निम्त्यायो। जर्मनी पक्ष शक्तिहरूले पनि भिन्नै सन्धिहरु गरेका थिए।<ref> {{cite book|editor1-last=Davis|editor1-first =Robert T.|title=U.S. Foreign Policy and National Security: Chronology and Index for the 20th Century|publisher=Praeger Security International|location=Santa Barbara, California|volume=1|year= 2010|page=[https://books.google.com/books?id=gsM1JiXAMJEC&pg=PA49 49]|isbn=978-0-313-38385-4}}</ref> सन्धिमा हस्ताक्षर गर्नु अघि जर्मनीलाई वार्तामा भाग लिन अनुमति थिएन।<ref>{{Cite book|title=The Treaty of Versailles: a reassessment after 75 years|date=1998|publisher=German Historical Institute; Cambridge University Press|isbn=978-0-521-62132-8|editor-last=Boemeke|editor-first=Manfred F.|series=Publications of the German Historical Institute|location=Washington, D.C.: Cambridge, UK; New York, NY|editor-last2=Feldman|editor-first2=Gerald D.|editor-last3=Gläser|editor-first3=Elisabeth}}</ref> यस सन्धि [[राष्ट्र सङ्घ|लिग अफ नेसन्स]]को सचिवालयमा २१ अक्टोबर १९९९ मा दर्ता भएको थियो।<ref>{{Cite book|title=The Treaty of Versailles: a reassessment after 75 years|date=1998|publisher=German Historical Institute; Cambridge University Press|isbn=978-0-521-62132-8|editor-last=Boemeke|editor-first=Manfred F.|series=Publications of the German Historical Institute|location=Washington, D.C.: Cambridge, UK; New York, NY|editor-last2=Feldman|editor-first2=Gerald D.|editor-last3=Gläser|editor-first3=Elisabeth}}</ref> उक्त सन्धिमा जर्मनीले निशस्त्रीकरण गर्नुपर्ने, भुभाग त्याग्नुपर्ने, कथित युद्ध अपराधीहरूलाई सुपुर्दगी गर्नुपर्ने, कैसर विल्हेल्मलाई मुद्दा चलाउन सहमति जनाउनुपर्ने, पहिले [[जर्मनेली साम्राज्य|जर्मन साम्राज्य]]को हिस्सा रहेको राज्यहरूको स्वतन्त्रतालाई मान्यता दिनुपर्ने र मित्र शक्तिहरूलाई क्षतिपूर्ति दिनुपर्ने व्यवस्था गरिएको थियो। सन्धिमा सबैभन्दा महत्वपूर्ण र विवादास्पद प्रावधान थियो: "जर्मनी र यसका सहयोगीहरूको आक्रमणद्वारा उनीहरूमाथि लगाइएको युद्धको परिणामस्वरूप मित्र राष्ट्र र सम्बद्ध सरकारहरू र उनीहरूका नागरिकहरूलाई भएको सबै हानि र क्षतिको जिम्मेवारी जर्मनी स्वीकार गर्दछ र सहयोगी र सम्बद्ध सरकारहरू पुष्टि गर्दछ।"<ref>{{Cite book|last=Neiberg|first=Michael S.|title=The Treaty of Versailles: a concise history|date=2017|publisher=Oxford University Press|isbn=978-0-19-065918-9|location=New York, NY}}</ref> केन्द्रीय शक्तिका अन्य सदस्यहरूले समान लेखहरू भएका सन्धिहरूमा हस्ताक्षर गरे। यो धारा २३१, "युद्ध अपराध" खण्डको रूपमा परिचित भएको छ। जोन मेनार्ड केन्स लगायतका आलोचकहरूले सन्धिलाई धेरै कठोर भएको बताए, यसलाई "कार्थाजिनियन शान्ति" को उपमा दिए। उनले क्षतिपूर्ति अत्यधिक र प्रतिउत्पादक पनि भने। अन्यले क्षतिपूर्तिले आगामी अति उच्च मुद्रास्फिति सिर्जना गरेको पुर्‍याएको बताए। अर्कोतर्फ, फ्रान्सेली मार्शल फर्डिनान्ड फोच जस्ता प्रमुख मित्र राष्ट्रहरूले जर्मनीलाई धेरै उदार व्यवहार गरेकोमा सन्धिको आलोचना गरे। यो सन्धी अझै पनि इतिहासकारहरू र अर्थशास्त्रीहरूद्वारा चलिरहेको बहसको विषय हो। विजेताहरू बीचको यी प्रतिस्पर्धात्मक र द्वन्द्वात्मक लक्ष्यहरूको परिणामस्वरूप एउटा सम्झौता भयो जसले कसैलाई पनि सन्तुष्ट पार्न सकेन। विशेष गरी, जर्मनी न त शान्त भयो, न त मेलमिलाप भयो, न त यो स्थायी रूपमा कमजोर नै भयो। संयुक्त राज्य अमेरिकाले कहिल्यै भर्साइल सन्धिलाई अनुमोदन गरेन; बरु यसले भर्साइल सन्धिको आधारमा जर्मनीसँग छुट्टै शान्ति सन्धि गर्यो। सन्धिबाट उत्पन्न समस्याहरूले लोकार्नो सन्धिहरू निम्त्यायो, जसले जर्मनी र अन्य युरोपेली शक्तिहरू बीचको सम्बन्धमा सुधार ल्यायो। क्षतिपूर्ति प्रणाली पुनर्गठन गरियो र भुक्तानी कम भयो। सन्धिप्रतिको तीतो आक्रोशले [[नाजी पार्टी]]को उदयलाई बल दियो, र अन्ततः [[दोस्रो विश्वयुद्ध]]को सुरुवात भयो। यसलाई प्रायः "भर्साइल्स सम्मेलन" भनिए पनि, सन्धिको ऐतिहासिक दरबारमा वास्तविक हस्ताक्षर मात्र भएको थियो। धेरैजसो वार्ताहरू पेरिसमा भएका थिए, "बिग फोर" (संयुक्त राज्य अमेरिका, संयुक्त अधिराज्य, फ्रान्स, इटाली) बैठकहरू सामान्यतया फ्रान्सेली विदेश मन्त्रालयमा क्वाई डी'ओरसेमा हुने गर्थे। ==पृष्ठभुमि == ===प्रथम विश्व युद्ध=== {{main|प्रथम विश्व युद्ध}} [[File:The signing of the peace treaty of Versailles.webm|thumb|thumbtime=00:01:45|Newsreel footage of the signing of the peace treaty at Versailles]] २८ जुन १९१४ मा, अष्ट्रिया हंगेरीको गद्दीका उत्तराधिकारी, आर्कड्युक फ्रान्ज फर्डिनान्डको सर्बियाली राष्ट्रवादीद्वारा हत्या भयो।{{sfn|Tucker|Roberts|2005|pp=xxv, 9}} यसको कारणले युरोपको माहोल तीव्र गतिमा बिग्रियो जसकारण अस्ट्रिया हंगेरीले सर्बिया बिरुद्ध युद्धको घोषणा गर्यो। त्यसपछी अधिकांश युरोपेली सैनिकहरू तुरुन्तै पहिलो विश्व युद्धमा प्रवेश गरे।{{sfn|Tucker|Roberts|2005|p=1078}} जर्मनीको नेतृत्वको केन्द्रिय शक्ति र (बेलायत, फ्रान्स र रसिया नेतृत्वको) त्रि पक्षीय गुट एक आपसमा भिडे। युरोप, मध्य पूर्व अफ्रिका र एसियामा विश्व युद्धको आगो सल्किदै गएपछी अन्य देशहरू पनि युद्धमा छिरे। १९१७ मा, [[रुसी साम्राज्य]] मा दुई क्रान्ति भए। त्यसपछि [[भ्लादिमिर लेनिन]]को नेतृत्वमा बनेको नयाँ बोल्सेभिक सरकारले १९१८ मार्चमा जर्मनी सँग सन्धिमा हस्ताक्षर गर्यो, जुन धेरै हदसम्म जर्मनको पक्षमा थियो। अमेरिकी सैनिक तयार हुनुभन्दा अगाडि [[विजय]] हासिल गर्न सकिने भएकाले, जर्मनीले अब आफ्नो बल पश्चिमी मोर्चामा तैनाथ गर्यो र एलाइज शक्तिलाई डुबाउने प्रयास गर्यो। तर त्यो प्रयास असफल रह्यो। तर त्यस विपरित, एलाइज शक्तिले निर्णायक रुपमा रणभुमीमा [[विजय]] पाए र नोबेम्बर १९१८ मा युद्धविराममा हस्ताक्षरको लागि बाध्य बनाए जुन आत्मसमर्पणको समान थियो । {{sfn|Wiest|2012|pp=126, 168, 200}} === युद्धविराम === [[चित्र:Western_front_1918_allied.jpg|पाठ=|अङ्गुठाकार|Map showing the Western Front as it stood on 11 November 1918. The German frontier of 1914 had been crossed in the vicinities of [[Mulhouse]], [[Château-Salins]], and [[Marieulles]] in Alsace-Lorraine. The post-war bridgeheads over the Rhine are also shown.]] १९१८ को शरद ऋतुमा, केन्द्रीय शक्तिहरू पतन हुन थाले।{{sfn|Beller|2007|pp=182–195}} जर्मन सेना भित्र पलायन दर बढ्न थाल्यो, र आमनागरिक हडतालहरूले युद्ध उत्पादनमा उल्लेखनीय कमी ल्यायो।{{sfn|Bessel|1993|pp=47–48}}{{sfn|Hardach|1987|pp=183–184}} पश्चिमी मोर्चामा, मित्र राष्ट्रहरूले सय दिनको आक्रमण सुरु गरे र जर्मन पश्चिमी सेनाहरूलाई निर्णायक रूपमा पराजित गरे। {{sfn|Simkins|2002|p=71}} किलमा इम्पेरियल जर्मन नौसेनाका नाविकहरूले २४ अक्टोबर १९१८ को नौसेना आदेशको प्रतिक्रियामा विद्रोह गरे, जसले जर्मनीमा विद्रोह निम्त्यायो। यसलाई [[जर्मन क्रान्ति]]को रूपमा चिनिन्छ।{{sfn|Tucker|Roberts|2005|p=638}}{{sfn|Schmitt|1960|p=101}} जर्मन सरकारले चौध बुँदाहरूमा आधारित शान्ति सम्झौता प्राप्त गर्ने प्रयास गर्‍यो, र यसै आधारमा उनीहरूले आत्मसमर्पण गरेको दाबी गर्‍यो। वार्ता पछि, मित्र राष्ट्रहरू र जर्मनीले [[युद्धविराम]]मा हस्ताक्षर गरे, जुन नोभेम्बर ११ मा लागू भयो जबकि जर्मन सेनाहरू अझै फ्रान्स र बेल्जियममा तैनाथ थिए।{{sfn|Schmitt|1960|p=102}}{{sfn|Weinberg|1994|p=8}}{{sfn|Boyer|Clark|Hawley|Kett|2009|p=526}} भर्साय सन्धिका धेरै पक्षहरू, जसको पछी आलोचना भयो, त्यसमा सबैभन्दा पहिले ११ नभेम्बरको युद्धबिराम सम्झौतामा सहमति भएको थियो, जबकि युद्ध अझै पनि चलिरहेको थियो। यसमा जर्मनीको कब्जामा रहेको फ्रान्स, बेल्जियम, लक्जमबर्ग, अलसेस-लोरेन र राइनको बायाँ किनारबाट जर्मनी बाहिरिनुपर्ने  (यी सबै क्षेत्रमा युद्धबिराम सम्झौताअनुसार मित्र शक्तिको प्रशासन चल्ने कुरा थियो), ठूलो मात्रामा युद्ध सामग्रीको आत्मसमर्पण, र "युद्धको क्षतिको क्षतिपूर्ति" को भुक्तानीमा सहमति समावेश थियो।{{sfn|Gilbert|1974|pp=270–273}} युद्धविराम सम्झौता अनुसार आवश्यक पन्ध्र दिन भित्र जर्मन सेनाले कब्जा गरेको फ्रान्स, बेल्जियम र लक्जमबर्ग खाली गरायो।{{sfn|Edmonds|1943|p=1}} १९१८ को अन्त्यतिर, मित्र राष्ट्रका सेनाहरू जर्मनीमा प्रवेश गरिसकेका थिए र सम्झौता अन्तर्गत राइनल्याण्डको कब्जा सुरु गरेका थिए, यस प्रक्रियामा कोलोन, कोब्लेन्ज र मेन्जमा नयाँ लडाईंको अवस्थामा राइनमा पुल निर्माण गरिएको थियो। मित्र राष्ट्र र जर्मन सेनाहरूलाई थप १० किलोमिटर चौडा असैन्यीकृत क्षेत्रद्वारा अलग गरिनु पर्ने थियो।{{sfn|Martel|1999|p=18}}{{sfn|Barnes|Ebertowski|2011|p=14}} === नाकाबन्दी === जर्मनी र ग्रेट ब्रिटेन दुवै खाद्यान्न र कच्चा पदार्थको आयातमा निर्भर थिए, जसमध्ये धेरैजसो एट्लान्टिक महासागर पार गरेर ढुवानी गर्नुपर्थ्यो। जर्मनीको नाकाबन्दी केन्द्रीय शक्तिहरूमा पुग्ने कच्चा पदार्थ र खाद्य पदार्थहरूको आपूर्ति रोक्न मित्र राष्ट्रहरूले सञ्चालन गरेको नौसेना अभियान थियो। जर्मन कैसरलिच मरीन मुख्यतया जर्मन बाइटमा सीमित थियो र प्रति-नाकाबन्दीको लागि पनडुब्बी युद्ध प्रयोग गर्थ्यो। डिसेम्बर १९१८ मा जर्मन जनस्वास्थ्य बोर्डले मित्र राष्ट्रहरूको नाकाबन्दीको समयमा ७६३,००० जर्मन नागरिकहरूको मृत्यु भएको बताएको थियो, यद्यपि १९२८ मा गरिएको एक शैक्षिक अध्ययनले मृत्युको संख्या ४२४,००० जना रहेको बताएको थियो।{{sfn|Grebler|1940|p=78}} नोभेम्बर १९१८ मा युद्धविराम पछि आठ महिनासम्म नाकाबन्दी कायम रह्यो। जर्मनीसँगको युद्धविराम पछि जर्मनीले जुन १९१९ मा भर्साइलको सन्धिमा हस्ताक्षर नगरेसम्म जर्मनीमा खाद्य पदार्थको आयात मित्र राष्ट्रहरूद्वारा नियन्त्रण गरिएको थियो। {{sfn|Mowat|1968|p=213}} मार्च १९१९ मा, [[विन्स्टन चर्चिल]]ले [[हाउस अफ कमन्स, संयुक्त अधिराज्य|हाउस अफ कमन्स]]लाई जानकारी गराए कि जारी नाकाबन्दी सफल भएको छ र "जर्मनी भोकमरीको धेरै नजिक छ।" {{sfn|Fuller|1993}} जनवरी १९१९ देखि मार्च १९१९ सम्म, जर्मनीले खाद्य आपूर्ति ढुवानी गर्न मित्र राष्ट्रहरूको बन्दरगाहहरूमा आफ्ना व्यापारी जहाजहरू आत्मसमर्पण गर्ने मित्र राष्ट्रहरूको मागहरू स्वीकार गर्न अस्वीकार गर्यो। केही जर्मनहरूले युद्धविरामलाई युद्धको अस्थायी अन्त्य मान्थे र थाहा थियो कि यदि फेरि लडाईं सुरु भयो भने, तिनीहरूका जहाजहरू कब्जा गरिनेछ।{{sfn|Marks|2013|p=650}} १९१९ को जाडोमा, स्थिति निराशाजनक भयो र जर्मनी अन्ततः मार्चमा आफ्नो बेडा आत्मसमर्पण गर्न सहमत भयो। {{sfn|March 1919 Brussels agreement}} त्यसपछि मित्र राष्ट्रहरूले २७०,००० टन खाद्य पदार्थ आयात गर्न अनुमति दिए।{{sfn|March 1919 Brussels agreement}} जर्मन र गैर-जर्मन दुवै पर्यवेक्षकहरूले तर्क गरेका छन् कि जर्मन नागरिकहरूका लागि नाकाबन्दीको यी सबैभन्दा विनाशकारी महिनाहरू थिए,{{sfn|Paul|1985|p=145}} यद्यपि कति हदसम्म र वास्तवमा कसको गल्ती छ भन्ने बारेमा असहमति कायम छ।{{sfn|Marks|2013|p=651}}{{sfn|''Proceedings of the National Assembly''|1919|pp=631–635}}{{sfn|''Deutsche Allgemeine Zeitung''|1919}}{{sfn|Roerkohl|1991|p=348}}{{sfn|Rudloff|1998|p=184}} म्याक्स रुबनरका अनुसार युद्धविराम पछि निरन्तर नाकाबन्दीका कारण १,००,००० जर्मन नागरिकहरूको मृत्यु भयो।{{sfn|Rubner|1919|p=15}} बेलायतमा, [[लेबर पार्टी (संयुक्त अधिराज्य)|लेबर पार्टी]]का सदस्य र युद्ध विरोधी कार्यकर्ता रोबर्ट स्मिलीले जुन १९१९ मा नाकाबन्दीको निरन्तरताको निन्दा गर्दै एक विज्ञप्ति जारी गरे, जसमा नाकाबन्दीको परिणामस्वरूप १,००,००० जर्मन नागरिकहरूको मृत्यु भएको दाबी गरिएको थियो।<ref>''Common Sense'' 5 July 1919.</ref>{{sfn|Bane|1942|p=791}} ==भर्सेलिज सन्धिका मुख्य प्रावधान== ===राष्ट्रसंघ=== [[राष्ट्र सङ्घ|राष्ट्रसंघ]]को निर्माण एवं संगठन भर्सेलिज-सन्धिको एक अत्यन्त महत्वपूर्ण अंग थियो। सन्धिको प्रथम भागको सम्बन्ध यो संग नै छ। यो मूलतः राष्ट्रपति [[उड्रो विल्सन|विल्सन]]को सृजना थियो। उसका विचार थियो कि राष्ट्रसंघलाई शान्ति-सम्मेलनको सबैभन्दा महान कृति मानिनेछ। लायड जर्जले लेखेका छन् विल्सन शान्ति-सन्धिको केवल उक्त भागलाई जसमा राष्ट्रसंघ व्यवस्था थियो, सबैभन्दा अधिक महत्व दिने गर्थे। यसको लागि उनी जे पनि त्याग गर्न तयार थिए र उनको प्रयासबाट नै राष्ट्रसंघ को निर्माण भयो। विल्सन बाहेक मित्रराष्ट्रका अन्य प्रतिनिधिहरूले यो विचार थियो कि राष्ट्रसंघ सम्बन्धी कुरा भर्सेलिज सन्धिको अन्तर्गत राख्न आवश्यक छैन। अन्ततः विल्सनको कुरा मानियो र राष्ट्रसंघको संविधानलाई भर्सेलिज सन्धिको अन्तर्गत नै राखियो । भर्सेलिज सन्धीको प्रथम २६ धाराहरू राष्ट्रसंघको संविधान नै हो, जसको उद्देश्य अन्तर्राष्ट्रीय सहयोगलाई बढाउनु तथा अन्तर्राष्ट्रीय शान्ति र सुरक्षालाई कायम राख्नु थियो। === क्षेत्रीय व्यवस्था/प्रणाली === === एल्सेस-लरेन क्षेत्र: === भर्सेलिज सन्धिमा क्षेत्रीय परिवर्तन गरि जर्मनीलाई अंग-भंग गरियो। १८७१ मा, जर्मनीले फ्रान्सबाट एल्सेस-लरेनको क्षेत्रमा कब्जा गरेको थियो। सबैले एक स्वरले "यो एक गलत काम थियो र यसको अन्त्य आवश्यक छ" भनेर स्विकार गरे। त्यसकारण, सन्धिका सर्तहरू बमोजिम, एल्सेस-लोरेन फ्रान्सले फिर्ता पायो। '''राइन ल्याण्ड''' : फ्रान्सको सुरक्षाको दृष्टि ले जर्मनीको राइन ल्याण्ड मा मित्र राष्ट्रहरूको सेना १५ वर्ष सम्म रहनेछ तथा राइन नदी आस-पासको क्षेत्रलाई स्थाई रूप ले निःशस्त्र गरियो ताकि जर्मनी कुनै प्रकारको किलाबन्दी गर्न नसकुन्। '''सार क्षेत्र''' : सार क्षेत्र जर्मनीमा कोइला क्षेत्रको लागि प्रसिद्ध थियो । यो प्रदेशको शासन व्यवस्थाको जिम्मेवारी राष्ट्रसंघलाई दिइयो तर कोइला खानीको स्वामित्व फ्रान्सलाई दिइयो। यो पनि तय गरियो कि १५ वर्ष पछी [[जनमत सङ्ग्रह]]द्वारा सारा क्षेत्रको बासिन्दा जर्मनी को साथ् रहन चाहन्छन् कि फ्रान्सको साथ तय गरिनेछ । यदि सारवासी जर्मनीको साथ मिल्न चाहन्छन् भने जर्मनी फ्रान्सलाई निश्चित मूल्य दिएर ती खानीहरू पुनः खरीद गर्नेछ । '''बेल्जियम एवं डेनमार्क की प्राप्ति''' : यूपेन मार्शनेट र मलमेडीको प्रदेश बेल्जियमको अधीन गरियो। श्लेशविगमा जनमत संग्रह गरेर त्यहाँको उत्तरी भाग डेनमार्कलाई दिइयो । '''जर्मनीको पूर्वी सीमा''' : जर्मनीलाई सबैभन्दा अधिक क्षति पूर्वी सीमामा उठाउनु पर्यो । मित्र राष्ट्रहरूले एक स्वतन्त्र पोल्याण्ड राज्य को निर्माणको निर्णय गरे । डान्जिङलाई स्वतन्त्र नगरको रूपमा परिवर्तित गरियो र उसलाई राष्ट्र संघको संरक्षणमा राखियो । पोल्याण्डलाई समुद्री मार्ग दिनको लागि डाजिंगको बन्दरगाहको उपयोग गर्ने अधिकार दिइयो। मेमेलको बन्दरगाह जर्मनीबाट खोसेर लिथुआनियालाई दिइयो । जर्मनीले चेकोस्लोवाकियालाई राज्य को मान्यता दियो । यस प्रकार प्रादेशिक व्यवस्थाको कारण जर्मनी को २५ हजार वर्ग मीलको प्रदेश र ७० लाखको जनसंख्या गुमाउनु पर्यो । '''जर्मन उपनिवेश सम्बंधी व्यवस्था''' : मित्र राष्ट्र जर्मन उपनिवेशहरूलाई आफ्नो आफ्नो साम्राज्यमा मिलाउन चाहन्थे तर विल्सनले यसको कडा विरोध गरे। [[उड्रो विल्सन|वुड्रो विल्सन]]को विरोधको कारण, मित्र राष्ट्रहरूले संरक्षण प्रणाली सुरु गरे। यसको अर्थ यो थियो कि जुन देश एकदम पिछदिएको छ, त्यस देशको समुचित कल्याण र विकास गर्नु । सभ्य राष्ट्रमा पवित्र धरोहरको रूप राष्ट्रसंघको तर्फाबाट त्यस देशको उन्नतिको लागि दिन पर्छ। Mindet व्यवस्थाको माध्यमले जर्मनीलाई आआफ्नो सबै उपनिवेश त्याग्नु पर्यो र ती उपनीवेशालाई मित्र-राष्ट्रको संरक्षणमा राखियो। प्रशान्त महासागरको कयौ द्विप तथा अफ्रीकी महादेशमा स्थित उपनिवेश जर्मनीले गुमाउनु पर्यो । === सैन्य प्रणाली === जर्मनेली सेनाको अधिकतम सङ्ख्या १ लाख बनाइएको थियो। यसको अतिरिक्त, नौसेना शक्ति पनि सीमित रहेको थियो। जर्मनीमा मात्र नौसेनाको ६ युद्धक्षेत्रलाई अनुमति दिइएको थियो भने सहयोगीहरूका पनडुब्बीहरूलाई कम लगाउने बारे छलफल गरिएको थियो। === वित्तीय प्रणाली === === नैतिक दायित्व === सन्धिको २३१ औँ सन्धिको अनुसार जर्मनी सबै क्षति र युद्धको लागि जिम्मेवार बनाइयो। === राजनीतिक व्यवस्था === राष्ट्रसंघको स्थापना राजनीतिक प्रणाली अन्तर्गत भर्सेलिजको सन्धिको एक महत्त्वपूर्ण भाग थियो। [[संयुक्त राष्ट्र सङ्घ|संयुक्त राष्ट्रसंघ]]को उद्देश्य अन्तर्राष्ट्रिय सहयोग र सुरक्षा कायम राख्नु थियो। == सन्धिको मूल्याङ्कन == ==सन्दर्भ सामग्रीहरू== {{reflist}} ==बाह्य कडीहरू== [[श्रेणी:दोस्रो विश्व युद्ध]] 71uz9worakeshs162ouqzrbrqae22k4 1361186 1361185 2026-06-12T03:22:50Z Bishaldev100 28807 /* नाकाबन्दी */ 1361186 wikitext text/x-wiki [[File:Treaty of Versailles, English version.jpg|thumb|{{{image_alt}}}|alt={{{image_alt}}}|thumb|भर्सिल्स् सन्धिको बाहिरी आवरण, अङ्गरेजी संस्करण]] '''भर्सेलिजको सन्धि''' ({{lang-en|Treaty of Versailles}} {{lang-fr|Traité de Versailles}}) २८ जुन १९१९ मा हस्ताक्षर गरिएको शान्ति सन्धि थियो। [[पहिलो विश्वयुद्ध|प्रथम विश्वयुद्ध]]को सबैभन्दा महत्त्वपूर्ण सन्धिको रूपमा, यसले जर्मनी र अधिकांश मित्र राष्ट्रहरू बीचको युद्धको अवस्थाको अन्त्य गर्‍यो। आर्कड्यूक फ्रान्ज फर्डिनान्डको हत्या (उक्त घटना विश्व युद्धको कारण )को ठीक पाँच वर्ष पछि भर्साइलको दरबारमा हस्ताक्षर गरिएको थियो, जसले युद्ध निम्त्यायो। जर्मनी पक्ष शक्तिहरूले पनि भिन्नै सन्धिहरु गरेका थिए।<ref> {{cite book|editor1-last=Davis|editor1-first =Robert T.|title=U.S. Foreign Policy and National Security: Chronology and Index for the 20th Century|publisher=Praeger Security International|location=Santa Barbara, California|volume=1|year= 2010|page=[https://books.google.com/books?id=gsM1JiXAMJEC&pg=PA49 49]|isbn=978-0-313-38385-4}}</ref> सन्धिमा हस्ताक्षर गर्नु अघि जर्मनीलाई वार्तामा भाग लिन अनुमति थिएन।<ref>{{Cite book|title=The Treaty of Versailles: a reassessment after 75 years|date=1998|publisher=German Historical Institute; Cambridge University Press|isbn=978-0-521-62132-8|editor-last=Boemeke|editor-first=Manfred F.|series=Publications of the German Historical Institute|location=Washington, D.C.: Cambridge, UK; New York, NY|editor-last2=Feldman|editor-first2=Gerald D.|editor-last3=Gläser|editor-first3=Elisabeth}}</ref> यस सन्धि [[राष्ट्र सङ्घ|लिग अफ नेसन्स]]को सचिवालयमा २१ अक्टोबर १९९९ मा दर्ता भएको थियो।<ref>{{Cite book|title=The Treaty of Versailles: a reassessment after 75 years|date=1998|publisher=German Historical Institute; Cambridge University Press|isbn=978-0-521-62132-8|editor-last=Boemeke|editor-first=Manfred F.|series=Publications of the German Historical Institute|location=Washington, D.C.: Cambridge, UK; New York, NY|editor-last2=Feldman|editor-first2=Gerald D.|editor-last3=Gläser|editor-first3=Elisabeth}}</ref> उक्त सन्धिमा जर्मनीले निशस्त्रीकरण गर्नुपर्ने, भुभाग त्याग्नुपर्ने, कथित युद्ध अपराधीहरूलाई सुपुर्दगी गर्नुपर्ने, कैसर विल्हेल्मलाई मुद्दा चलाउन सहमति जनाउनुपर्ने, पहिले [[जर्मनेली साम्राज्य|जर्मन साम्राज्य]]को हिस्सा रहेको राज्यहरूको स्वतन्त्रतालाई मान्यता दिनुपर्ने र मित्र शक्तिहरूलाई क्षतिपूर्ति दिनुपर्ने व्यवस्था गरिएको थियो। सन्धिमा सबैभन्दा महत्वपूर्ण र विवादास्पद प्रावधान थियो: "जर्मनी र यसका सहयोगीहरूको आक्रमणद्वारा उनीहरूमाथि लगाइएको युद्धको परिणामस्वरूप मित्र राष्ट्र र सम्बद्ध सरकारहरू र उनीहरूका नागरिकहरूलाई भएको सबै हानि र क्षतिको जिम्मेवारी जर्मनी स्वीकार गर्दछ र सहयोगी र सम्बद्ध सरकारहरू पुष्टि गर्दछ।"<ref>{{Cite book|last=Neiberg|first=Michael S.|title=The Treaty of Versailles: a concise history|date=2017|publisher=Oxford University Press|isbn=978-0-19-065918-9|location=New York, NY}}</ref> केन्द्रीय शक्तिका अन्य सदस्यहरूले समान लेखहरू भएका सन्धिहरूमा हस्ताक्षर गरे। यो धारा २३१, "युद्ध अपराध" खण्डको रूपमा परिचित भएको छ। जोन मेनार्ड केन्स लगायतका आलोचकहरूले सन्धिलाई धेरै कठोर भएको बताए, यसलाई "कार्थाजिनियन शान्ति" को उपमा दिए। उनले क्षतिपूर्ति अत्यधिक र प्रतिउत्पादक पनि भने। अन्यले क्षतिपूर्तिले आगामी अति उच्च मुद्रास्फिति सिर्जना गरेको पुर्‍याएको बताए। अर्कोतर्फ, फ्रान्सेली मार्शल फर्डिनान्ड फोच जस्ता प्रमुख मित्र राष्ट्रहरूले जर्मनीलाई धेरै उदार व्यवहार गरेकोमा सन्धिको आलोचना गरे। यो सन्धी अझै पनि इतिहासकारहरू र अर्थशास्त्रीहरूद्वारा चलिरहेको बहसको विषय हो। विजेताहरू बीचको यी प्रतिस्पर्धात्मक र द्वन्द्वात्मक लक्ष्यहरूको परिणामस्वरूप एउटा सम्झौता भयो जसले कसैलाई पनि सन्तुष्ट पार्न सकेन। विशेष गरी, जर्मनी न त शान्त भयो, न त मेलमिलाप भयो, न त यो स्थायी रूपमा कमजोर नै भयो। संयुक्त राज्य अमेरिकाले कहिल्यै भर्साइल सन्धिलाई अनुमोदन गरेन; बरु यसले भर्साइल सन्धिको आधारमा जर्मनीसँग छुट्टै शान्ति सन्धि गर्यो। सन्धिबाट उत्पन्न समस्याहरूले लोकार्नो सन्धिहरू निम्त्यायो, जसले जर्मनी र अन्य युरोपेली शक्तिहरू बीचको सम्बन्धमा सुधार ल्यायो। क्षतिपूर्ति प्रणाली पुनर्गठन गरियो र भुक्तानी कम भयो। सन्धिप्रतिको तीतो आक्रोशले [[नाजी पार्टी]]को उदयलाई बल दियो, र अन्ततः [[दोस्रो विश्वयुद्ध]]को सुरुवात भयो। यसलाई प्रायः "भर्साइल्स सम्मेलन" भनिए पनि, सन्धिको ऐतिहासिक दरबारमा वास्तविक हस्ताक्षर मात्र भएको थियो। धेरैजसो वार्ताहरू पेरिसमा भएका थिए, "बिग फोर" (संयुक्त राज्य अमेरिका, संयुक्त अधिराज्य, फ्रान्स, इटाली) बैठकहरू सामान्यतया फ्रान्सेली विदेश मन्त्रालयमा क्वाई डी'ओरसेमा हुने गर्थे। ==पृष्ठभुमि == ===प्रथम विश्व युद्ध=== {{main|प्रथम विश्व युद्ध}} [[File:The signing of the peace treaty of Versailles.webm|thumb|thumbtime=00:01:45|Newsreel footage of the signing of the peace treaty at Versailles]] २८ जुन १९१४ मा, अष्ट्रिया हंगेरीको गद्दीका उत्तराधिकारी, आर्कड्युक फ्रान्ज फर्डिनान्डको सर्बियाली राष्ट्रवादीद्वारा हत्या भयो।{{sfn|Tucker|Roberts|2005|pp=xxv, 9}} यसको कारणले युरोपको माहोल तीव्र गतिमा बिग्रियो जसकारण अस्ट्रिया हंगेरीले सर्बिया बिरुद्ध युद्धको घोषणा गर्यो। त्यसपछी अधिकांश युरोपेली सैनिकहरू तुरुन्तै पहिलो विश्व युद्धमा प्रवेश गरे।{{sfn|Tucker|Roberts|2005|p=1078}} जर्मनीको नेतृत्वको केन्द्रिय शक्ति र (बेलायत, फ्रान्स र रसिया नेतृत्वको) त्रि पक्षीय गुट एक आपसमा भिडे। युरोप, मध्य पूर्व अफ्रिका र एसियामा विश्व युद्धको आगो सल्किदै गएपछी अन्य देशहरू पनि युद्धमा छिरे। १९१७ मा, [[रुसी साम्राज्य]] मा दुई क्रान्ति भए। त्यसपछि [[भ्लादिमिर लेनिन]]को नेतृत्वमा बनेको नयाँ बोल्सेभिक सरकारले १९१८ मार्चमा जर्मनी सँग सन्धिमा हस्ताक्षर गर्यो, जुन धेरै हदसम्म जर्मनको पक्षमा थियो। अमेरिकी सैनिक तयार हुनुभन्दा अगाडि [[विजय]] हासिल गर्न सकिने भएकाले, जर्मनीले अब आफ्नो बल पश्चिमी मोर्चामा तैनाथ गर्यो र एलाइज शक्तिलाई डुबाउने प्रयास गर्यो। तर त्यो प्रयास असफल रह्यो। तर त्यस विपरित, एलाइज शक्तिले निर्णायक रुपमा रणभुमीमा [[विजय]] पाए र नोबेम्बर १९१८ मा युद्धविराममा हस्ताक्षरको लागि बाध्य बनाए जुन आत्मसमर्पणको समान थियो । {{sfn|Wiest|2012|pp=126, 168, 200}} === युद्धविराम === [[चित्र:Western_front_1918_allied.jpg|पाठ=|अङ्गुठाकार|Map showing the Western Front as it stood on 11 November 1918. The German frontier of 1914 had been crossed in the vicinities of [[Mulhouse]], [[Château-Salins]], and [[Marieulles]] in Alsace-Lorraine. The post-war bridgeheads over the Rhine are also shown.]] १९१८ को शरद ऋतुमा, केन्द्रीय शक्तिहरू पतन हुन थाले।{{sfn|Beller|2007|pp=182–195}} जर्मन सेना भित्र पलायन दर बढ्न थाल्यो, र आमनागरिक हडतालहरूले युद्ध उत्पादनमा उल्लेखनीय कमी ल्यायो।{{sfn|Bessel|1993|pp=47–48}}{{sfn|Hardach|1987|pp=183–184}} पश्चिमी मोर्चामा, मित्र राष्ट्रहरूले सय दिनको आक्रमण सुरु गरे र जर्मन पश्चिमी सेनाहरूलाई निर्णायक रूपमा पराजित गरे। {{sfn|Simkins|2002|p=71}} किलमा इम्पेरियल जर्मन नौसेनाका नाविकहरूले २४ अक्टोबर १९१८ को नौसेना आदेशको प्रतिक्रियामा विद्रोह गरे, जसले जर्मनीमा विद्रोह निम्त्यायो। यसलाई [[जर्मन क्रान्ति]]को रूपमा चिनिन्छ।{{sfn|Tucker|Roberts|2005|p=638}}{{sfn|Schmitt|1960|p=101}} जर्मन सरकारले चौध बुँदाहरूमा आधारित शान्ति सम्झौता प्राप्त गर्ने प्रयास गर्‍यो, र यसै आधारमा उनीहरूले आत्मसमर्पण गरेको दाबी गर्‍यो। वार्ता पछि, मित्र राष्ट्रहरू र जर्मनीले [[युद्धविराम]]मा हस्ताक्षर गरे, जुन नोभेम्बर ११ मा लागू भयो जबकि जर्मन सेनाहरू अझै फ्रान्स र बेल्जियममा तैनाथ थिए।{{sfn|Schmitt|1960|p=102}}{{sfn|Weinberg|1994|p=8}}{{sfn|Boyer|Clark|Hawley|Kett|2009|p=526}} भर्साय सन्धिका धेरै पक्षहरू, जसको पछी आलोचना भयो, त्यसमा सबैभन्दा पहिले ११ नभेम्बरको युद्धबिराम सम्झौतामा सहमति भएको थियो, जबकि युद्ध अझै पनि चलिरहेको थियो। यसमा जर्मनीको कब्जामा रहेको फ्रान्स, बेल्जियम, लक्जमबर्ग, अलसेस-लोरेन र राइनको बायाँ किनारबाट जर्मनी बाहिरिनुपर्ने  (यी सबै क्षेत्रमा युद्धबिराम सम्झौताअनुसार मित्र शक्तिको प्रशासन चल्ने कुरा थियो), ठूलो मात्रामा युद्ध सामग्रीको आत्मसमर्पण, र "युद्धको क्षतिको क्षतिपूर्ति" को भुक्तानीमा सहमति समावेश थियो।{{sfn|Gilbert|1974|pp=270–273}} युद्धविराम सम्झौता अनुसार आवश्यक पन्ध्र दिन भित्र जर्मन सेनाले कब्जा गरेको फ्रान्स, बेल्जियम र लक्जमबर्ग खाली गरायो।{{sfn|Edmonds|1943|p=1}} १९१८ को अन्त्यतिर, मित्र राष्ट्रका सेनाहरू जर्मनीमा प्रवेश गरिसकेका थिए र सम्झौता अन्तर्गत राइनल्याण्डको कब्जा सुरु गरेका थिए, यस प्रक्रियामा कोलोन, कोब्लेन्ज र मेन्जमा नयाँ लडाईंको अवस्थामा राइनमा पुल निर्माण गरिएको थियो। मित्र राष्ट्र र जर्मन सेनाहरूलाई थप १० किलोमिटर चौडा असैन्यीकृत क्षेत्रद्वारा अलग गरिनु पर्ने थियो।{{sfn|Martel|1999|p=18}}{{sfn|Barnes|Ebertowski|2011|p=14}} === नाकाबन्दी === जर्मनी र ग्रेट ब्रिटेन दुवै [[खाद्यान्न]] र [[कच्चा पदार्थ]]को आयातमा निर्भर थिए, जसमध्ये धेरैजसो [[आन्ध्र महासागर|एट्लान्टिक महासागर]] पार गरेर ढुवानी गर्नुपर्थ्यो। मित्र राष्ट्रहरूले सञ्चालन गरेको जर्मनीको नाकाबन्दी केन्द्रीय शक्तिहरूमा पुग्ने कच्चा पदार्थ र खाद्य पदार्थहरूको आपूर्ति रोक्न नौसेना अभियान थियो। जर्मन कैसरलिच मरीन मुख्यतया जर्मन बाइटमा सीमित थियो र प्रति-नाकाबन्दीको लागि [[पनडुब्बी]] युद्ध प्रयोग गर्थ्यो। डिसेम्बर १९१८ मा जर्मन जनस्वास्थ्य बोर्डले मित्र राष्ट्रहरूको नाकाबन्दीको समयमा ७६३,००० जर्मन नागरिकहरूको मृत्यु भएको बताएको थियो, यद्यपि १९२८ मा गरिएको एक शैक्षिक अध्ययनले मृत्युको संख्या ४२४,००० जना रहेको बताएको थियो।{{sfn|Grebler|1940|p=78}} नोभेम्बर १९१८ मा युद्धविराम पछि आठ महिनासम्म नाकाबन्दी कायम रह्यो। जर्मनीसँगको युद्धविराम पछि जर्मनीले जुन १९१९ मा भर्साइलको सन्धिमा हस्ताक्षर नगरेसम्म जर्मनीमा खाद्य पदार्थको आयात मित्र राष्ट्रहरूद्वारा नियन्त्रण गरिएको थियो। {{sfn|Mowat|1968|p=213}} मार्च १९१९ मा, [[विन्स्टन चर्चिल]]ले [[हाउस अफ कमन्स, संयुक्त अधिराज्य|हाउस अफ कमन्स]]लाई जानकारी गराए कि जारी नाकाबन्दी सफल भएको छ र "जर्मनी [[भोकमरी]]को धेरै नजिक छ।" {{sfn|Fuller|1993}} जनवरी १९१९ देखि मार्च १९१९ सम्म, जर्मनीले खाद्य आपूर्ति ढुवानी गर्न मित्र राष्ट्रहरूको बन्दरगाहहरूमा आफ्ना व्यापारी जहाजहरू आत्मसमर्पण गर्ने मित्र राष्ट्रहरूको मागहरू स्वीकार गर्न अस्वीकार गर्यो। केही जर्मनहरूले युद्धविरामलाई युद्धको अस्थायी अन्त्य मान्थे र थाहा थियो कि यदि फेरि लडाईं सुरु भयो भने, तिनीहरूका जहाजहरू कब्जा गरिनेछ।{{sfn|Marks|2013|p=650}} १९१९ को जाडोमा, स्थिति निराशाजनक भयो र जर्मनी अन्ततः मार्चमा आफ्नो बेडा आत्मसमर्पण गर्न सहमत भयो। {{sfn|March 1919 Brussels agreement}} त्यसपछि मित्र राष्ट्रहरूले २७०,००० टन खाद्य पदार्थ आयात गर्न अनुमति दिए।{{sfn|March 1919 Brussels agreement}} जर्मन र गैर-जर्मन दुवै पर्यवेक्षकहरूले तर्क गरेका छन् कि जर्मन नागरिकहरूका लागि नाकाबन्दीको यी सबैभन्दा विनाशकारी महिनाहरू थिए,{{sfn|Paul|1985|p=145}} यद्यपि कति हदसम्म र वास्तवमा कसको गल्ती छ भन्ने बारेमा असहमति कायम छ।{{sfn|Marks|2013|p=651}}{{sfn|''Proceedings of the National Assembly''|1919|pp=631–635}}{{sfn|''Deutsche Allgemeine Zeitung''|1919}}{{sfn|Roerkohl|1991|p=348}}{{sfn|Rudloff|1998|p=184}} म्याक्स रुबनरका अनुसार युद्धविराम पछि निरन्तर नाकाबन्दीका कारण १,००,००० जर्मन नागरिकहरूको मृत्यु भयो।{{sfn|Rubner|1919|p=15}} बेलायतमा, [[लेबर पार्टी (संयुक्त अधिराज्य)|लेबर पार्टी]]का सदस्य र युद्ध विरोधी कार्यकर्ता रोबर्ट स्मिलीले जुन १९१९ मा नाकाबन्दीको निरन्तरताको निन्दा गर्दै एक विज्ञप्ति जारी गरे, जसमा नाकाबन्दीको परिणामस्वरूप १,००,००० जर्मन नागरिकहरूको मृत्यु भएको दाबी गरिएको थियो।<ref>''Common Sense'' 5 July 1919.</ref>{{sfn|Bane|1942|p=791}} ==भर्सेलिज सन्धिका मुख्य प्रावधान== ===राष्ट्रसंघ=== [[राष्ट्र सङ्घ|राष्ट्रसंघ]]को निर्माण एवं संगठन भर्सेलिज-सन्धिको एक अत्यन्त महत्वपूर्ण अंग थियो। सन्धिको प्रथम भागको सम्बन्ध यो संग नै छ। यो मूलतः राष्ट्रपति [[उड्रो विल्सन|विल्सन]]को सृजना थियो। उसका विचार थियो कि राष्ट्रसंघलाई शान्ति-सम्मेलनको सबैभन्दा महान कृति मानिनेछ। लायड जर्जले लेखेका छन् विल्सन शान्ति-सन्धिको केवल उक्त भागलाई जसमा राष्ट्रसंघ व्यवस्था थियो, सबैभन्दा अधिक महत्व दिने गर्थे। यसको लागि उनी जे पनि त्याग गर्न तयार थिए र उनको प्रयासबाट नै राष्ट्रसंघ को निर्माण भयो। विल्सन बाहेक मित्रराष्ट्रका अन्य प्रतिनिधिहरूले यो विचार थियो कि राष्ट्रसंघ सम्बन्धी कुरा भर्सेलिज सन्धिको अन्तर्गत राख्न आवश्यक छैन। अन्ततः विल्सनको कुरा मानियो र राष्ट्रसंघको संविधानलाई भर्सेलिज सन्धिको अन्तर्गत नै राखियो । भर्सेलिज सन्धीको प्रथम २६ धाराहरू राष्ट्रसंघको संविधान नै हो, जसको उद्देश्य अन्तर्राष्ट्रीय सहयोगलाई बढाउनु तथा अन्तर्राष्ट्रीय शान्ति र सुरक्षालाई कायम राख्नु थियो। === क्षेत्रीय व्यवस्था/प्रणाली === === एल्सेस-लरेन क्षेत्र: === भर्सेलिज सन्धिमा क्षेत्रीय परिवर्तन गरि जर्मनीलाई अंग-भंग गरियो। १८७१ मा, जर्मनीले फ्रान्सबाट एल्सेस-लरेनको क्षेत्रमा कब्जा गरेको थियो। सबैले एक स्वरले "यो एक गलत काम थियो र यसको अन्त्य आवश्यक छ" भनेर स्विकार गरे। त्यसकारण, सन्धिका सर्तहरू बमोजिम, एल्सेस-लोरेन फ्रान्सले फिर्ता पायो। '''राइन ल्याण्ड''' : फ्रान्सको सुरक्षाको दृष्टि ले जर्मनीको राइन ल्याण्ड मा मित्र राष्ट्रहरूको सेना १५ वर्ष सम्म रहनेछ तथा राइन नदी आस-पासको क्षेत्रलाई स्थाई रूप ले निःशस्त्र गरियो ताकि जर्मनी कुनै प्रकारको किलाबन्दी गर्न नसकुन्। '''सार क्षेत्र''' : सार क्षेत्र जर्मनीमा कोइला क्षेत्रको लागि प्रसिद्ध थियो । यो प्रदेशको शासन व्यवस्थाको जिम्मेवारी राष्ट्रसंघलाई दिइयो तर कोइला खानीको स्वामित्व फ्रान्सलाई दिइयो। यो पनि तय गरियो कि १५ वर्ष पछी [[जनमत सङ्ग्रह]]द्वारा सारा क्षेत्रको बासिन्दा जर्मनी को साथ् रहन चाहन्छन् कि फ्रान्सको साथ तय गरिनेछ । यदि सारवासी जर्मनीको साथ मिल्न चाहन्छन् भने जर्मनी फ्रान्सलाई निश्चित मूल्य दिएर ती खानीहरू पुनः खरीद गर्नेछ । '''बेल्जियम एवं डेनमार्क की प्राप्ति''' : यूपेन मार्शनेट र मलमेडीको प्रदेश बेल्जियमको अधीन गरियो। श्लेशविगमा जनमत संग्रह गरेर त्यहाँको उत्तरी भाग डेनमार्कलाई दिइयो । '''जर्मनीको पूर्वी सीमा''' : जर्मनीलाई सबैभन्दा अधिक क्षति पूर्वी सीमामा उठाउनु पर्यो । मित्र राष्ट्रहरूले एक स्वतन्त्र पोल्याण्ड राज्य को निर्माणको निर्णय गरे । डान्जिङलाई स्वतन्त्र नगरको रूपमा परिवर्तित गरियो र उसलाई राष्ट्र संघको संरक्षणमा राखियो । पोल्याण्डलाई समुद्री मार्ग दिनको लागि डाजिंगको बन्दरगाहको उपयोग गर्ने अधिकार दिइयो। मेमेलको बन्दरगाह जर्मनीबाट खोसेर लिथुआनियालाई दिइयो । जर्मनीले चेकोस्लोवाकियालाई राज्य को मान्यता दियो । यस प्रकार प्रादेशिक व्यवस्थाको कारण जर्मनी को २५ हजार वर्ग मीलको प्रदेश र ७० लाखको जनसंख्या गुमाउनु पर्यो । '''जर्मन उपनिवेश सम्बंधी व्यवस्था''' : मित्र राष्ट्र जर्मन उपनिवेशहरूलाई आफ्नो आफ्नो साम्राज्यमा मिलाउन चाहन्थे तर विल्सनले यसको कडा विरोध गरे। [[उड्रो विल्सन|वुड्रो विल्सन]]को विरोधको कारण, मित्र राष्ट्रहरूले संरक्षण प्रणाली सुरु गरे। यसको अर्थ यो थियो कि जुन देश एकदम पिछदिएको छ, त्यस देशको समुचित कल्याण र विकास गर्नु । सभ्य राष्ट्रमा पवित्र धरोहरको रूप राष्ट्रसंघको तर्फाबाट त्यस देशको उन्नतिको लागि दिन पर्छ। Mindet व्यवस्थाको माध्यमले जर्मनीलाई आआफ्नो सबै उपनिवेश त्याग्नु पर्यो र ती उपनीवेशालाई मित्र-राष्ट्रको संरक्षणमा राखियो। प्रशान्त महासागरको कयौ द्विप तथा अफ्रीकी महादेशमा स्थित उपनिवेश जर्मनीले गुमाउनु पर्यो । === सैन्य प्रणाली === जर्मनेली सेनाको अधिकतम सङ्ख्या १ लाख बनाइएको थियो। यसको अतिरिक्त, नौसेना शक्ति पनि सीमित रहेको थियो। जर्मनीमा मात्र नौसेनाको ६ युद्धक्षेत्रलाई अनुमति दिइएको थियो भने सहयोगीहरूका पनडुब्बीहरूलाई कम लगाउने बारे छलफल गरिएको थियो। === वित्तीय प्रणाली === === नैतिक दायित्व === सन्धिको २३१ औँ सन्धिको अनुसार जर्मनी सबै क्षति र युद्धको लागि जिम्मेवार बनाइयो। === राजनीतिक व्यवस्था === राष्ट्रसंघको स्थापना राजनीतिक प्रणाली अन्तर्गत भर्सेलिजको सन्धिको एक महत्त्वपूर्ण भाग थियो। [[संयुक्त राष्ट्र सङ्घ|संयुक्त राष्ट्रसंघ]]को उद्देश्य अन्तर्राष्ट्रिय सहयोग र सुरक्षा कायम राख्नु थियो। == सन्धिको मूल्याङ्कन == ==सन्दर्भ सामग्रीहरू== {{reflist}} ==बाह्य कडीहरू== [[श्रेणी:दोस्रो विश्व युद्ध]] 99k0ye7nou0yiu7ot5qv8muft5wfc9k राज्याभिषेक 0 97529 1361489 791736 2026-06-12T11:21:10Z Bishaldev100 28807 1361489 wikitext text/x-wiki [[चित्र:Ram Rajyabhishek.jpg|300px|thumb|भगवान रामको राज्याभिषेक गरिंदै]] '''राज्याभिषेक''' एक वैदिक संस्कार हो । यस कार्यक्रमा नयाँ राजकुमारलाई आज देखी [[राजा]] भए भन्ने घोषणा गरिन्छ । यो समयमा, राज्यका अन्य अधिकारीहरूको पनि नियुक्तिको घोषणा गरिन्छ। ==यो पनि हेर्नुहोस्== * [[राजसूय]] <gallery class="center" widths="200px" heights="200px"> King Tribhuvan Bir Bikram Shah in his coronation robe.png|राजा त्रिभुवनको राज्याभिषेक, ५ वर्षको उमेर King Mahendra Bir Bikram Shah and Queen Ratna Rajya Lakshmi Devi, shortly after the King’s coronation, 1955.jpg|२०१३ साल राजा महेन्द्र, रानी रत्न राज्याभिषेकमा </gallery> ==सन्दर्भ== {{सन्दर्भसूची}} {{ठुटो}} [[श्रेणी:संस्कार]] sfdqih9tqc6fpacgqnajf1x0jzmifqi 1361490 1361489 2026-06-12T11:23:08Z Bishaldev100 28807 /* यो पनि हेर्नुहोस् */ 1361490 wikitext text/x-wiki [[चित्र:Ram Rajyabhishek.jpg|300px|thumb|भगवान रामको राज्याभिषेक गरिंदै]] '''राज्याभिषेक''' एक वैदिक संस्कार हो । यस कार्यक्रमा नयाँ राजकुमारलाई आज देखी [[राजा]] भए भन्ने घोषणा गरिन्छ । यो समयमा, राज्यका अन्य अधिकारीहरूको पनि नियुक्तिको घोषणा गरिन्छ। ==यो पनि हेर्नुहोस्== * [[राजसूय]] <gallery class="center" widths="200px" heights="200px"> Jacques-Louis David - The Coronation of Napoleon (1805-1807).jpg|thumb|२ डिसेम्बर १८०४ मा ज्याक-लुइस डेभिडद्वारा नोट्रे डेमको क्याथेड्रलमा नेपोलियनको राज्याभिषेक King Tribhuvan Bir Bikram Shah in his coronation robe.png|राजा त्रिभुवनको राज्याभिषेक, ५ वर्षको उमेर King Mahendra Bir Bikram Shah and Queen Ratna Rajya Lakshmi Devi, shortly after the King’s coronation, 1955.jpg|२०१३ साल राजा महेन्द्र, रानी रत्न राज्याभिषेकमा </gallery> ==सन्दर्भ== {{सन्दर्भसूची}} {{ठुटो}} [[श्रेणी:संस्कार]] j5roovo2zkj5hauo2ahwv30k67xrb6w 1361491 1361490 2026-06-12T11:24:55Z Bishaldev100 28807 /* यो पनि हेर्नुहोस् */ 1361491 wikitext text/x-wiki [[चित्र:Ram Rajyabhishek.jpg|300px|thumb|भगवान रामको राज्याभिषेक गरिंदै]] '''राज्याभिषेक''' एक वैदिक संस्कार हो । यस कार्यक्रमा नयाँ राजकुमारलाई आज देखी [[राजा]] भए भन्ने घोषणा गरिन्छ । यो समयमा, राज्यका अन्य अधिकारीहरूको पनि नियुक्तिको घोषणा गरिन्छ। ==यो पनि हेर्नुहोस्== * [[राजसूय]] <gallery class="center" widths="200px" heights="200px"> Jacques-Louis David - The Coronation of Napoleon (1805-1807).jpg|२ डिसेम्बर १८०४ मा ज्याक-लुइस डेभिडद्वारा चित्रित नोट्रे डेम क्याथेड्रलमा [[नेपोलियन बोनापार्ट|नेपोलियन]]को राज्याभिषेक King Tribhuvan Bir Bikram Shah in his coronation robe.png|[[त्रिभुवन वीरविक्रम शाह|राजा त्रिभुवन]]को राज्याभिषेक, ५ वर्षको उमेर King Mahendra Bir Bikram Shah and Queen Ratna Rajya Lakshmi Devi, shortly after the King’s coronation, 1955.jpg|२०१३ साल [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]], रानी रत्न राज्याभिषेकमा </gallery> ==सन्दर्भ== {{सन्दर्भसूची}} {{ठुटो}} [[श्रेणी:संस्कार]] hxz2fi7m3brmi2x83s2ywdvz5cht664 1361492 1361491 2026-06-12T11:26:25Z Bishaldev100 28807 /* यो पनि हेर्नुहोस् */ 1361492 wikitext text/x-wiki [[चित्र:Ram Rajyabhishek.jpg|300px|thumb|भगवान रामको राज्याभिषेक गरिंदै]] '''राज्याभिषेक''' एक वैदिक संस्कार हो । यस कार्यक्रमा नयाँ राजकुमारलाई आज देखी [[राजा]] भए भन्ने घोषणा गरिन्छ । यो समयमा, राज्यका अन्य अधिकारीहरूको पनि नियुक्तिको घोषणा गरिन्छ। ==यो पनि हेर्नुहोस्== * [[राजसूय]] <gallery class="center" widths="200px" heights="200px"> Jacques-Louis David - The Coronation of Napoleon (1805-1807).jpg|२ डिसेम्बर १८०४ मा ज्याक-लुइस डेभिडद्वारा चित्रित नोट्रे डेम क्याथेड्रलमा [[नेपोलियन बोनापार्ट|नेपोलियन]]को राज्याभिषेक King Tribhuvan Bir Bikram Shah in his coronation robe.png|[[त्रिभुवन वीरविक्रम शाह|राजा त्रिभुवन]]को राज्याभिषेक, ५ वर्षको उमेर King Mahendra Bir Bikram Shah and Queen Ratna Rajya Lakshmi Devi, shortly after the King’s coronation, 1955.jpg|२०१३ साल [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]], रानी रत्न राज्याभिषेकमा CoronationShahanshahShahbanou.jpg|thumb|१९६७ मा मोहम्मद रेजा शाह र फराह पहलवीको राज्याभिषेक। </gallery> ==सन्दर्भ== {{सन्दर्भसूची}} {{ठुटो}} [[श्रेणी:संस्कार]] lfo5val4ek41n2vtpc2dmoneqcpl0jc 1361493 1361492 2026-06-12T11:26:39Z Bishaldev100 28807 /* यो पनि हेर्नुहोस् */ 1361493 wikitext text/x-wiki [[चित्र:Ram Rajyabhishek.jpg|300px|thumb|भगवान रामको राज्याभिषेक गरिंदै]] '''राज्याभिषेक''' एक वैदिक संस्कार हो । यस कार्यक्रमा नयाँ राजकुमारलाई आज देखी [[राजा]] भए भन्ने घोषणा गरिन्छ । यो समयमा, राज्यका अन्य अधिकारीहरूको पनि नियुक्तिको घोषणा गरिन्छ। ==यो पनि हेर्नुहोस्== * [[राजसूय]] <gallery class="center" widths="200px" heights="200px"> Jacques-Louis David - The Coronation of Napoleon (1805-1807).jpg|२ डिसेम्बर १८०४ मा ज्याक-लुइस डेभिडद्वारा चित्रित नोट्रे डेम क्याथेड्रलमा [[नेपोलियन बोनापार्ट|नेपोलियन]]को राज्याभिषेक King Tribhuvan Bir Bikram Shah in his coronation robe.png|[[त्रिभुवन वीरविक्रम शाह|राजा त्रिभुवन]]को राज्याभिषेक, ५ वर्षको उमेर King Mahendra Bir Bikram Shah and Queen Ratna Rajya Lakshmi Devi, shortly after the King’s coronation, 1955.jpg|२०१३ साल [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]], रानी रत्न राज्याभिषेकमा CoronationShahanshahShahbanou.jpg|१९६७ मा [[मोहमद रेजा पहलवी|मोहम्मद रेजा शाह]] र फराह पहलवीको राज्याभिषेक। </gallery> ==सन्दर्भ== {{सन्दर्भसूची}} {{ठुटो}} [[श्रेणी:संस्कार]] 7jco6tuk48h0wavchmokk2ttt2qumvs 1361494 1361493 2026-06-12T11:30:42Z Bishaldev100 28807 1361494 wikitext text/x-wiki [[चित्र:Ram Rajyabhishek.jpg|300px|thumb|भगवान रामको राज्याभिषेक गरिंदै]] '''राज्याभिषेक''' एक वैदिक संस्कार हो । यस कार्यक्रमा नयाँ राजा पहिलो पल्ट विधिपूर्वक राजगद्दीमा बस्दा प्रचलन स८स्कार अनुसार अभिषेक गरिन्छ । प्राय: दिवंगत भएका राजाको वर्षदिनको काम पुरा भएपछि राजाको राज्याभिषेक हुन्छ । नयाँ राजकुमारलाई आज देखी [[राजा]] भए भन्ने घोषणा गरिन्छ । यो समयमा, राज्यका अन्य अधिकारीहरूको पनि नियुक्तिको घोषणा गरिन्छ। ==यो पनि हेर्नुहोस्== * [[राजसूय]] <gallery class="center" widths="200px" heights="200px"> Jacques-Louis David - The Coronation of Napoleon (1805-1807).jpg|२ डिसेम्बर १८०४ मा ज्याक-लुइस डेभिडद्वारा चित्रित नोट्रे डेम क्याथेड्रलमा [[नेपोलियन बोनापार्ट|नेपोलियन]]को राज्याभिषेक King Tribhuvan Bir Bikram Shah in his coronation robe.png|[[त्रिभुवन वीरविक्रम शाह|राजा त्रिभुवन]]को राज्याभिषेक, ५ वर्षको उमेर King Mahendra Bir Bikram Shah and Queen Ratna Rajya Lakshmi Devi, shortly after the King’s coronation, 1955.jpg|२०१३ साल [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]], रानी रत्न राज्याभिषेकमा CoronationShahanshahShahbanou.jpg|१९६७ मा [[मोहमद रेजा पहलवी|मोहम्मद रेजा शाह]] र फराह पहलवीको राज्याभिषेक। </gallery> ==सन्दर्भ== {{सन्दर्भसूची}} {{ठुटो}} [[श्रेणी:संस्कार]] 5mwetewmzgkqp5pl2kq20zzztw8oac6 1361495 1361494 2026-06-12T11:32:18Z Bishaldev100 28807 1361495 wikitext text/x-wiki [[चित्र:Ram Rajyabhishek.jpg|300px|thumb|भगवान रामको राज्याभिषेक गरिंदै]] '''राज्याभिषेक''' एक वैदिक संस्कार हो । यस कार्यक्रमा नयाँ राजा पहिलो पल्ट विधिपूर्वक राजगद्दीमा बस्दा प्रचलन स८स्कार अनुसार अभिषेक गरिन्छ । प्राय: दिवंगत भएका राजाको वर्षदिनको [[श्राद्ध]] काम पुरा भएपछि राजाको शुभ मुर्हुत निकालेर राज्याभिषेक हुन्छ । नयाँ राजकुमारलाई आज देखी [[राजा]] भए भन्ने घोषणा गरिन्छ । यो समयमा, राज्यका अन्य अधिकारीहरूको पनि नियुक्तिको घोषणा गरिन्छ। ==यो पनि हेर्नुहोस्== * [[राजसूय]] <gallery class="center" widths="200px" heights="200px"> Jacques-Louis David - The Coronation of Napoleon (1805-1807).jpg|२ डिसेम्बर १८०४ मा ज्याक-लुइस डेभिडद्वारा चित्रित नोट्रे डेम क्याथेड्रलमा [[नेपोलियन बोनापार्ट|नेपोलियन]]को राज्याभिषेक King Tribhuvan Bir Bikram Shah in his coronation robe.png|[[त्रिभुवन वीरविक्रम शाह|राजा त्रिभुवन]]को राज्याभिषेक, ५ वर्षको उमेर King Mahendra Bir Bikram Shah and Queen Ratna Rajya Lakshmi Devi, shortly after the King’s coronation, 1955.jpg|२०१३ साल [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]], रानी रत्न राज्याभिषेकमा CoronationShahanshahShahbanou.jpg|१९६७ मा [[मोहमद रेजा पहलवी|मोहम्मद रेजा शाह]] र फराह पहलवीको राज्याभिषेक। </gallery> ==सन्दर्भ== {{सन्दर्भसूची}} {{ठुटो}} [[श्रेणी:संस्कार]] nvqegqspmvrm2j95ymut8v7twbcibnv 1361496 1361495 2026-06-12T11:42:11Z Bishaldev100 28807 /* यो पनि हेर्नुहोस् */ 1361496 wikitext text/x-wiki [[चित्र:Ram Rajyabhishek.jpg|300px|thumb|भगवान रामको राज्याभिषेक गरिंदै]] '''राज्याभिषेक''' एक वैदिक संस्कार हो । यस कार्यक्रमा नयाँ राजा पहिलो पल्ट विधिपूर्वक राजगद्दीमा बस्दा प्रचलन स८स्कार अनुसार अभिषेक गरिन्छ । प्राय: दिवंगत भएका राजाको वर्षदिनको [[श्राद्ध]] काम पुरा भएपछि राजाको शुभ मुर्हुत निकालेर राज्याभिषेक हुन्छ । नयाँ राजकुमारलाई आज देखी [[राजा]] भए भन्ने घोषणा गरिन्छ । यो समयमा, राज्यका अन्य अधिकारीहरूको पनि नियुक्तिको घोषणा गरिन्छ। ==यो पनि हेर्नुहोस्== * [[राजसूय]] <gallery class="center" widths="200px" heights="200px"> Jacques-Louis David - The Coronation of Napoleon (1805-1807).jpg|२ डिसेम्बर १८०४ मा ज्याक-लुइस डेभिडद्वारा चित्रित नोट्रे डेम क्याथेड्रलमा [[नेपोलियन बोनापार्ट|नेपोलियन]]को राज्याभिषेक King Tribhuvan Bir Bikram Shah in his coronation robe.png|[[त्रिभुवन वीरविक्रम शाह|राजा त्रिभुवन]]को राज्याभिषेक, ५ वर्षको उमेर King Mahendra Bir Bikram Shah and Queen Ratna Rajya Lakshmi Devi, shortly after the King’s coronation, 1955.jpg|२०१३ साल [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]], रानी रत्न राज्याभिषेकमा CoronationShahanshahShahbanou.jpg|१९६७ मा [[मोहमद रेजा पहलवी|मोहम्मद रेजा शाह]] र फराह पहलवीको राज्याभिषेक। Coronation of King Gyanendra 2058 Jestha.jpg|thumb|राजा ज्ञानेन्द्र </gallery> ==सन्दर्भ== {{सन्दर्भसूची}} {{ठुटो}} [[श्रेणी:संस्कार]] bry9cd9m7lapcp46arflg0dvbhna3ca 1361497 1361496 2026-06-12T11:45:32Z Bishaldev100 28807 /* यो पनि हेर्नुहोस् */ 1361497 wikitext text/x-wiki [[चित्र:Ram Rajyabhishek.jpg|300px|thumb|भगवान रामको राज्याभिषेक गरिंदै]] '''राज्याभिषेक''' एक वैदिक संस्कार हो । यस कार्यक्रमा नयाँ राजा पहिलो पल्ट विधिपूर्वक राजगद्दीमा बस्दा प्रचलन स८स्कार अनुसार अभिषेक गरिन्छ । प्राय: दिवंगत भएका राजाको वर्षदिनको [[श्राद्ध]] काम पुरा भएपछि राजाको शुभ मुर्हुत निकालेर राज्याभिषेक हुन्छ । नयाँ राजकुमारलाई आज देखी [[राजा]] भए भन्ने घोषणा गरिन्छ । यो समयमा, राज्यका अन्य अधिकारीहरूको पनि नियुक्तिको घोषणा गरिन्छ। ==यो पनि हेर्नुहोस्== * [[राजसूय]] <gallery class="center" widths="200px" heights="200px"> Jacques-Louis David - The Coronation of Napoleon (1805-1807).jpg|२ डिसेम्बर १८०४ मा ज्याक-लुइस डेभिडद्वारा चित्रित नोट्रे डेम क्याथेड्रलमा [[नेपोलियन बोनापार्ट|नेपोलियन]]को राज्याभिषेक King Tribhuvan Bir Bikram Shah in his coronation robe.png|[[त्रिभुवन वीरविक्रम शाह|राजा त्रिभुवन]]को राज्याभिषेक, ५ वर्षको उमेर King Mahendra Bir Bikram Shah and Queen Ratna Rajya Lakshmi Devi, shortly after the King’s coronation, 1955.jpg|२०१३ साल [[महेन्द्र वीरविक्रम शाह|राजा महेन्द्र]], रानी रत्न राज्याभिषेकमा CoronationShahanshahShahbanou.jpg|१९६७ मा [[मोहमद रेजा पहलवी|मोहम्मद रेजा शाह]] र फराह पहलवीको राज्याभिषेक। Coronation of King Gyanendra 2058 Jestha.jpg|thumb|राजा ज्ञानेन्द्र Coronation balcony (52877063504) (cropped).jpg|thumb|[[चार्ल्स तृतीय]] र क्यामिलाको राज्याभिषेक </gallery> ==सन्दर्भ== {{सन्दर्भसूची}} {{ठुटो}} [[श्रेणी:संस्कार]] dn1wwqnmzevphedbnpinpkjerjj6r6u देङ सियाओपिङ 0 97762 1361171 1354815 2026-06-11T14:12:34Z Bishaldev100 28807 /* मृत्यु तथा प्रतिक्रिया */ 1361171 wikitext text/x-wiki {{Infobox officeholder |name = तेङ सियाओ फिङ |native_name = {{nobold|{{lang|zh-hans|邓小平}}}} |image = Deng Xiaoping.jpg |caption = सन् १९७९ मा सियाओ फिङ |order =[[केन्द्रीय सल्लाहकार आयोग|कम्युनिस्ट पार्टीका केन्द्रीय सल्लाहकार]] |deputy = पो इपो<br />सु सि-यु<br />खान चेनलिन<br />लि वेई-हान |1blankname = General&nbsp;Secretary |1namedata = हु इयाओपाङ<br />चाओ सियाङ |term = १३ सेप्टेम्बर १९८२ – २ नोभेम्बर १९८७ |predecessor = नवनिर्मित कार्यालय |successor = छेन युन |order1 = चीनको केन्द्रीय सैन्य आयोगका अध्यक्ष |term1 = २८ जुन १९८१ – ९ नोभेम्बर १९८९ |deputy1 = ये चियेन-इङ<br />चाओ सि-इयनङ<br />याङ साङखुन |predecessor1 = [[हुआ गोफेङ|हुआ गोआफेङ]] |successor1 = [[जियाङ जेमिन|जियाङ जेमिन]] |office2 = चिनियाँ नागरिक राजनैतिक परामर्श सम्मेलनका अध्यक्ष |term2 = ८ मार्च १९७८ – १७ जुन १९८३ |predecessor2 = [[झोउ एनलाइ|चाउ एन लाइ]]<br />खाली (सज् १९७६ – १९७८) |successor2 = तेङ याङचाओ |office3 = राष्ट्रिय काङ्ग्रेसका<br />सदस्य |constituency3 = |term3 = १८ अप्रिल १९८९ – २१ डिसेम्बर १९६८<br />२६ फेब्रुअरी १९७८ – १९ फेब्रुअरी १९९७ |order4 = जनवादी गणतन्त्र चीनका प्रथम उपाध्यक्ष |term4 = १७ जनवरी १९७५ – ७ अप्रिल १९७६<br />२१ जुलाई १९७७ – १० सेप्टेम्बर १९८० |predecessor4 = लिन बियाओ |successor4 = वान लि |premier4 = [[झोउ एनलाइ|चाउ एन लाई]]<br />[[हुआ गोफेङ]] |birth_date = {{birth date|1904|8|22|df=y}} |birth_place = सिचुआन, चीन |death_date = {{Death date and age|1997|2|19|1904|8|22|df=y}} |death_place = बेइजिङ |nationality = चिनियाँ |party = [[चिनियाँ कम्युनिस्ट पार्टी|चिनियाँ कम्युनिष्ट पार्टी]] |spouse = झाङ सियुआन (张锡瑗) (सन् १९२८–१९२९)<br />जिज वेइङ (金维映) (सन् १९३१–१९३९)<br />झोऊ लिज (卓琳) (सन् १९३९–१९९७) |children = तेङ लिज<br />तेङ फुफाङ<br />तेङ नान<br />तेङ रोङ<br />तेङ जिफाङ | allegiance = {{Flagicon image|Flag of the People's Republic of China.svg|size=23px}} [[चीन|जनवादी गणतन्त्र चीन]] | branch = {{Flagicon image|Flag of the People's Liberation Army.svg|size=23px}} [[जनमुक्ति सेना, चीन]] <br/> {{Flagicon image|中國工農紅軍軍旗.svg|size=23px}} [[चिनिया लाल सेना]] | serviceyears = १९२९-१९५२ [[चिनियाँ लाल सेना]] <br/> १९७५-१९८० [[जनमुक्ति सेना, चीन|जनमुक्ति सेना]] | rank = | battles = [[चिनियाँ गृहयुद्ध]] <br/> [[दोस्रो चीन-जापानी युद्ध|द्वितीय चीन-जापान युद्ध]] | mawards = |signature = }} {{Chinese|s=邓小平|t=鄧小平|p=Dèng Xiǎopíng|w=Teng Hsiao-p'ing|myr|Deng Syauping|altname=Deng Xiansheng|s2=邓先圣|t2=鄧先聖|p2=Dèng Xiānshèng|w2=Teng Hsien-sheng|altname3=Deng Xixian|s3=邓希贤|t3=鄧希賢|p3=Dèng Xīxián|w3=Teng Hsi-hsien|order=st}} {{stack end}} '''तेङ सियाओ फिङ''' ({{भाषा-चिनियाँ|邓小平}}, २२ अगस्ट १९०४-१९ फेब्रुअरी १९९७); देङ शियाओ पिङ नामबाट लोकप्रिय ) एक चिनियाँ [[क्रान्तिकारी]] र राजनेता थिए। उनले सन् १९७८ डिसेम्बर देखि सन् १९८९ नोभेम्बर सम्म [[चीन|जनवादी चीन]]को प्रमुख नीति निर्माताको रूपमा काम गरेका थिए। सन् १९७६ मा [[माओ त्सेतुङ|माओ त्से तुङ्]]को मृत्यु पछि चीनको सत्तामा तेङको [[जनवादी गणतन्त्र चीनका सर्वोच्च नेता|सर्वोच्च नेता]]को रूपमा उदय भएको थियो भने उनले आफ्नो देशलाई दूरगामी बजार-आर्थिक सुधारको शृङ्खलाको नेतृत्व गरेका थिए जसबाट उनलाई "आधुनिक चीनको निर्माता"को रूपमा चिनिन्छ।<ref>{{Cite news|last=Faison|first=Seth|date=1997-02-20|title=DENG XIAOPING IS DEAD AT 92; ARCHITECT OF MODERN CHINA|language=en|work=The New York Times|url=https://www.nytimes.com/1997/02/20/world/deng-xiaoping-is-dead-at-92-architect-of-modern-china.html|access-date=2021-04-19|issn=0362-4331}}</ref> ==माओको मातहतमा राजनैतिक वृत्ति == === चेङकिङका नगर प्रमुख === १ अक्टोबर १९४९ मा, [[बेइजिङ]]मा भएको जनवादी गणतन्त्र चीनको घोषणामा देङ उपस्थित थिए। त्यतिबेला [[चिनियाँ कम्युनिस्ट पार्टी|कम्युनिष्ट पार्टी]]ले पुरै उत्तरी भुभागमा नियन्त्रण कायम गरेको थियो, तर दक्षिणको केही भागहरूमा कुमिन्ताङको शासन रहेको थियो। उनलाई दक्षिण पश्चिमी चीन शमन गर्ने जिम्मेवारीका साथ दक्षिण पश्चिम विभागको प्रथम सचिव बनाइएको थियो। यो सङ्गठनलाई कुमिन्ताङले कब्जा गरेका भुभागमा नियन्त्रण गर्ने जिम्मा दिइएको थियो भने तिब्बत अर्को एक वर्ष सम्म स्वतन्त्र रूपमा रहेको थियो। कुमिन्ताङ सरकार ग्वाङजाउ छोड्न बाध्य भएको थियो र चोङकिङमा नयाँ प्रादेशिक राजधानी स्थापना गरिएको थियो। त्यहाँ [[च्याङ काइसेक|चियाङ काइ सेक]] र उनका पुत्र चियाङ च्याङ कुओ, जो देङ मस्कोमा पढ्दा ताकाको सहकर्मी थिए, कम्युनिस्ट पार्टीको फौजलाई अघि बढ्न रोक्न चाहन्थेे। देङको राजनैतिक मातहतमा, कम्युनिष्ट सेनाले नोभेम्बरको अन्त्य सम्ममा चोङकिङ नियन्त्रणमा लिँदै केही दिन पछि [[च्याङ काइसेक|च्याङ काइ सेक]]को अन्तिम किल्ला रहेको चेङ्दु प्रवेश गरेको थियो। त्यहिबेला देङ चोङकिङको नगर प्रमुख बनेका थिए भने तात्कालिक समयमा उनी कम्युनिस्ट पार्टीको दक्षिण पश्चिमको नेताको रूपमा रहेका थिए। दक्षिण पश्चिममा कम्युनिस्टको [[जनमुक्ति सेना, चीन|जनमुक्ति सेना]]ले कुमिन्ताङ शासन प्रती दमन गरेको थियो। सन् १९५० मा, कम्युनिस्ट पार्टी शासित चीनले तिब्बतमा नियन्त्रण कायम गरेको थियो। देङ सियाओ पिङले चोङ्किङमा तीन वर्ष बिताएका थिए। उनले [[फ्रान्स]] जानुु भन्दा अघि किशोर अवस्थामा त्यहीँ पढाइ गरेका थिए। सन् १९५२ मा उनी बेइजिङ सरुवा भएका जहाँ उनले केन्द्रीय सरकारको विभिन्न पद हासिल गरेका थिए। === बेइजिङमा राजनैतिक उदय === {{मुख्य|महान अग्रगामी छलाङ}} जुलाई १९५२ मा, देङ बेइजिङ आएका थिए र उप प्रधानमन्त्री र अर्थ समितिको उपाध्यक्ष पद सम्हालेका थिए। उनले अर्थ मन्त्रीको पद र सञ्चार निर्देशकको पद सम्हालेको केही समयमा नै, उनलाई उप प्रधानमन्त्री बाहेक सबै पदबाट हटाइएको थियो। सन् १९५६ मा, उनी कम्युनिस्ट पार्टी सङ्गठन विभागको प्रमुख र केन्द्रिय सैन्य आयोगको सदस्य बनेका थिए। माओको सन् १९५७ को दक्षिणपन्थी-विरोधी आन्दोलनलाई औपचारिक समर्थन गरेपछि, देङ कम्युनिस्ट पार्टी केन्द्रिय कमिटीको सचिव बन्दै देशको दैनिक मामिला राष्ट्रपति लिउ साओकी र प्रधानमन्त्री [[झोउ एनलाइ|चाउ एन लाइ]]सँगै चलाउने भएका थिए। देङ र लिउको नीतिले वैचारिक सिद्धान्त भन्दा पनि आर्थिक सिद्धान्तलाई महत्त्व दिन्थ्यो। === दुई शुद्धीकरणको निशाना === {{मुख्य|चीनको सांस्कृतिक क्रान्ति}} ==== सांस्कृतिक क्रान्ति ==== माओलाई देङ र लिउको सुधारवादी आर्थिक नीतिले पूँजीवादको पुनर्स्थापना हुने र [[चिनियाँ क्रान्ति]]को अन्त्य हुने डर थियो। <ref name="autogenerated1">{{cite news | author=Minqi Li | title=Socialism, capitalism, and class struggle: The Political economy of Modern china | work = Economic & Political Weekly | date=December 2008}}</ref> यो र अन्य कारणहरूले गर्दा, माओले सन् १९६६ मा साँस्कृतिक क्रान्ति सुरु गरेका थिए। यस क्रममा देङ उनको निशानामा रहेका थिए र उनलाई सबै पदबाट हटाइएको थियो। साँस्कृतिक क्रान्तिको समयमा, उनलाई र उनको परिवारलाई रेड गार्डहरूले निशाना बनाए। रेड गार्डले उनको जेठो छोरा देङ पुफाङलाई कैद गरेका थिए। देङ पुफाङलाई यातना दिइएको थियो र सन् १९६८ मा चार तले भवनको झ्यालबाट बाहिर खसालिएको थियो। अक्टोबर १९६९ मा देङलाई जियाङ्सी प्रान्तको सिनजियानको ट्र्याक्टर कारखानामा मजदुरी काम गर्न पठाइएको थियो।<ref>{{cite web | url = http://www.chinadaily.com.cn/china/2007-07/10/content_6142550_5.htm | title = Deng Xiaoping − The Years of Hardship and Danger | publisher = People.com.cn | date = 10 July 2007 | access-date = 18 February 2011 | archive-url = https://web.archive.org/web/20180917215432/http://www.chinadaily.com.cn/china/2007-07/10/content_6142550_5.htm | archive-date = 17 September 2018 | url-status = live }}</ref> त्यहाँको चार वर्षमा,<ref>{{cite news | url=http://www.newsgd.com/specials/deng100thbirthanniversary/newspictures/200407280046.htm | title=Film makers flock to tractor factory to shoot Deng's stories | publisher=News Guandong | date=26 July 2004 | access-date=18 February 2011 | archive-url=https://web.archive.org/web/20180917215515/http://www.newsgd.com/specials/deng100thbirthanniversary/newspictures/200407280046.htm | archive-date=17 September 2018 | url-status=live }}</ref> देङले आफ्नो बाँकी समय लेखनमा बिताएका थिए। देङलाई लिउसँगै देशव्यापी रूपमा सार्वजनिक रुपमा अपमान र आलोचना गरिएको थियो। [[लिउ शाओकी|लिउ साओची]]को सन् १९६९ मा श्रम शिविरमा मृत्यु भएको थियो। ==सत्तारोहण तथा शासन == === सर्वोच्च नेता === [[File:Deng Xiaoping and Jimmy Carter at the arrival ceremony for the Vice Premier of China. - NARA - 183157-restored.jpg|thumb|देङ शियाओ पिङको अमेरिकी भ्रमण (१९७९)को आगमन समारोहमा देङ र [[जिम्मी कार्टर]]|alt=|250x250px]] ९ सेप्टेम्बर १९७६ मा माओको मृत्यु पछि र अक्टोबरमा चारको समुहको सफाया पछि, देङ [[जनवादी गणतन्त्र चीनका सर्वोच्च नेता|चीनको सर्वोच्च नेता]]को रुपमा उदाए। माओको निधन हुनुभन्दा अगाडि, उनले धारण गरेको सरकारी पद चीनको राज्य परिषदको उप प्रधानमन्त्री पद मात्र थियो। <ref>1975–1976 and 1977–1980, Europa Publications (2002) "The People's Republic of Chine: Introductory Survey" ''The Europa World Year Book 2003'' volume 1, (44th edition) Europa Publications, London, p. 1075, col. 1, {{ISBN|1-85743-227-4}}; and Bo, Zhiyue (2007) ''China's Elite Politics: Political Transition and Power Balancing'' World Scientific, Hackensack, New Jersey, p. 59, {{ISBN|981-270-041-2}}</ref> तर [[हुआ गोफेङ|ह्वा गोफेङ]] पार्टीलाई अतिवादी/ उग्रवामपन्थीहरूबाट मुक्त गर्न चाहन्थे र सफलतापूर्वक [[चारजनाको टोली|चारजनाको समुह]] ([[चारजनाको टोली|ग्याङ अफ फोर]])लाई किनारा लगाए। २२ जुलाई १९७७ मा, देङ "केन्द्रिय समिती"को उपाध्यक्ष, सैन्य परिषदको उपाध्यक्ष र [[जनमुक्ति सेना, चीन|जनमुक्ति सेना]]को प्रमुखको पदमा पुनर्स्थापित भए।<ref>{{cite news |url=http://news.bbc.co.uk/onthisday/hi/dates/stories/july/22/newsid_2516000/2516339.stm |title=1977: Deng Xiaoping back in power |work=BBC News |access-date=21 July 2011 |date=22 July 1977 |archive-url=https://web.archive.org/web/20170728025020/http://news.bbc.co.uk/onthisday/hi/dates/stories/july/22/newsid_2516000/2516339.stm |archive-date=28 July 2017 |url-status=live }}</ref> [[माओ त्सेतुङ|माओ]]का केही नीतिलाई लिएर सन् १९६० र ७० को दशकमा कैयौँ पटक झट्का बेहोरेपछि देङ सियाओपिङ सचेत भएका थिए। अन्तर्राष्ट्रिय सम्बन्धलाई लिएर देङ सियाओपिङ केही सिद्धान्तका साथ अघि बढ्ने गर्दथे। उनी आफूलाई मात्रै महत्त्वका साथ अग्रपंक्तिमा राख्दैनथे। उनले आफ्नो पूरै ध्यान चिनियाँ अर्थतन्त्रलाई तीव्र गतिका साथ अगाडि बढाउनमा केन्द्रित गरेका थिए। हार्वर्ड विश्वविद्यालयमा सामाजिक विज्ञान पढाउने प्राध्यापक एज्रा फोगेलले देङ सिआओपिङको जीवनी लेखेका छन्। उनले देङ सिआओपिङलाई अस्थिरतालाई रोक्दै स्थायित्व ल्याउन सक्ने क्षमता भएको एक महान् नेताका रूपमा चित्रण गरेका छन्। देशको अर्थतन्त्रमा भएको कायापलटसँगै चिनियाँ नागरिकमा आर्थिक सम्पन्नता मात्रै नआइ सत्तामा चिनियाँ कम्युनिष्ट पार्टीको पकड समेत मजबुत भएको छ। चीनमा देङ सिआओपिङको आर्थिक [[उदारवाद|उदारीकरण]]लाई राजनीतिक उदारीकरण पनि भनिन्छ। === विदेश मामिला === [[File:Visit of Chinese Vice Premier Deng Xiaoping to Johnson Space Center - GPN-2002-000077.jpg|thumb|left|देङ शियाओ पिङ (बायाँ) र उनको पत्नी (दायाँ) लाई सम्बोधन गर्दै जोनसन स्पेस सेन्टरका निर्देशक क्रिस्टोफर सि. क्राफ्ट]] नोभेम्बर १९७८ मा, राजनैतिक उलट लट स्थिर भएपछि, देङले [[बैंक ग्यारेन्टी|बैकक]], [[क्वालालम्पुर]] र [[सिङ्गापुर|सिंगापुर]]को भ्रमण गरे र सिंगापुरका प्रधानमन्त्री [[ली कुआन यु|लि क्वान यु]] सँग भेटे। सिंगापुरको आर्थिक विकास, हरियाली र आवास परियोजना, बाट देङ निकै प्रभावित भए। र पछि दसौं हजार चिनियाँ नागरिकहरूलाई सिंगापुर र विश्वका विभिन्न देशहरूमा त्यहाँको अनुभव सिक्न र त्यसको ज्ञानलाई चीन फिर्ता ल्याउन्को लागि पठाए। लि क्वान यु ले अर्को तर्फ, देङलाई दक्षिण पूर्वी एसियामा बामपन्थी विचारधारा निर्यात बन्द गर्न सुझाव दिए, जुन सुझाव पछि देङले अनुसरण गरे।<ref>{{cite web |url=http://app.mfa.gov.sg/2006/press/view_press_print.asp?post_id=1538 |title=MFA, Singapore Press Release |publisher=App.mfa.gov.sg |date=29 December 2005 |access-date=27 November 2011 |archive-url=https://web.archive.org/web/20120302193654/http://app.mfa.gov.sg/2006/press/view_press_print.asp?post_id=1538 |archive-date=2 March 2012 |url-status=dead }}</ref><ref>Lee Kuan Yew, ''From Third World to First: The Singapore Story, 1965–2000, Volume 2'', (HarperCollins: 2000), pp. 595–603</ref> १९७९ को पूर्वार्धमा, देङले [[संयुक्त राज्य अमेरिका]]को औपचारिक भ्रमण गरे। उनले राष्ट्रपति [[जिम्मी कार्टर]] र अन्य धेरै सांसद (कंग्रेसम्यान ) हरूसँग भेटवार्ता गरे। चीन जापान सम्बन्धमा पनि महत्वपूर्ण सुधार आयो।<ref>(Article 2) "The Contracting Parties declare that neither of them should seek [[hegemony]] in the Asia-Pacific region or in any other region and that each is opposed to efforts by any other country or group of countries to establish such hegemony." [http://www.mofa.go.jp/region/asia-paci/china/treaty78.html MOFA: Treaty of Peace and Friendship between Japan and the People's Republic of China] {{Webarchive|url=https://web.archive.org/web/20170609105736/http://www.mofa.go.jp/region/asia-paci/china/treaty78.html|date=9 June 2017}}</ref> देङले [[जापान]]लाई द्रुत गतिमा विकास गर्ने शक्तिको रुपमा उदाहरणको रुपमा प्रस्तुत गरे जसले चीनको आर्थिक विकासमा अनुकरणीय उदाहरण पेश गर्यो। === सुधार तथा आधुनिकीकरण === देङ सिआओपिङले प्राय बिरालो सिद्धान्त 'क्याट थिअरी' को कुरा गर्दथे अर्थात् ''बिरालोको रङ कालो वा सेतो हुनुले अर्थ राख्दैन, जबसम्म बिरालोले मुसा समातिरहन्छ तबसम्म त्यो राम्रो बिरालो नै कहलिन्छ।''<ref name=":0">[https://www.bbc.com/nepali/news-44610431 ४० वर्षमा चीन कसरी समृद्ध भयो?]</ref> सबैभन्दा पहिले उनले [[सोभियत सङ्घ]]को आर्थिक 'मोडल'लाई परित्याग गरे र चिनियाँ आवश्यकता अनुसारको अर्थतन्त्रमा आधुनिकीकरणलाई [[समाजवाद|समाजवाद]]का साथ अगाडि बढाए। चिनियाँ लेखक युकोन ख्वाङ आफ्नो पुस्तक 'क्र्याकिङ द चाइना कनन्ड्रमः ह्वाइ कन्भेन्सनल इकोनोमिक विज्डम इज रंग' मा लेखेका छन्, "देङ सिआओपिङ एक महान् सुधारक मात्रै थिएनन्, धैर्य नभएका व्यक्ति पनि थिए। " देङ सिआओपिङले शुरू गरेको सामाजिक-आर्थिक सुधारको दृष्टान्त मानव इतिहासमा भेटिँदैन। सन् १९७८ देखि २०१६ को बीचमा चीनको [[कुल ग्राहस्थ उत्पादन]]मा ३,२३० प्रतिशतले वृद्धि भएको छ। यसबीचमा ७० करोड मानिसहरू गरिबीको रेखाबाट माथि उठे भने ३८.५ करोड मानिसहरू [[मध्यम वर्ग]]का रूपमा उकासिए। चीनको वैदेशिक व्यापार साढे १७ हजार प्रतिशतले बढ्यो भने सन् २०१५ सम्म चीन विदेशी व्यापारमा अगुवाको रूपमा उदायो। सन् १९७८ मा चीनले वर्षभरि गर्ने व्यापार अहिले दुई दिनमै गर्छ। देङ सिआओपिङले [[चिनियाँ कम्युनिस्ट पार्टी|चिनियाँ कम्युनिष्ट पार्]]टीलाई सामूहिक नेतृत्वमा लगेर चीनमा सामाजिक-आर्थिक परिवर्तनको प्रक्रियामा तीव्रता दिए।<ref name=":0" /> ====चार आधुनिकीकरण ==== देङको पुरानो भनाइ उद्धरण गरेका थिए, " बिरालो कालो होस् वा सेतो होस् यसले फरक पर्दैन, यदि यसले मुसा समाउँछ भने यो राम्रो बिरालो हो।" <ref>{{cite book|author1=John Naisbitt|author2=Doris Naisbitt|title=China's Megatrends: The 8 Pillars of a New Society|url=https://archive.org/details/chinasmegatrends00nais_0|url-access=registration|year=2010|publisher=HarperBusiness|page=[https://archive.org/details/chinasmegatrends00nais_0/page/4 4]|isbn=9780061963445}}</ref> देङले आफ्नो समूह विशेष गरि चाओ जियाङ, जो १९८० मा प्रधानमन्त्री भए र हु याओबाङ जो १९८१ मा पार्टी अध्यक्ष बने, सँग काम गरे। देङले शक्तिमा पुगेपछि "चार आधुनिकीकरण" (अर्थतन्त्र, कृषि, बैज्ञानिक तथा प्राविधिक बिकास र राष्ट्रिय सुरक्षा)को लक्ष्य हासिल गर्ने प्राथमिकता दिए। उनले अर्थतन्त्रलाई खुला गर्ने तथा उदार गर्ने महत्वाकांक्षी योजनाको घोषणा गरे।<ref>David Mason, "China's Four Modernizations: Blueprint for Development or Prelude to Turmoil?." ''Asian Affairs'' 11.3 (1984): 47–70.</ref> देङको पहलमा, चिनियाँ कम्युनिस्ट पार्टीले अध्यक्ष पदलाई खारेज गर्यो र महासचिवलाई पार्टीको पदेन नेता बनायो। देङले ब्रेजनेभ र क्रमलिन सँगको सम्बन्ध सुधार गर्नको लागि आफ्नो शासनको प्रारम्भमा केही प्रयास पनि गरे। उनले चीन- सोभियत विभाजनको समयको माओको लाइनलाई सनर्थन गरे। सोभियत संघ संयुक्त राज्य जत्तिकै [[महाशक्ति]] हो, तर चीनको लागि उसको सिमा निकटताको कारणले जोखिमपूर्ण पनि छ। <ref>Michael E. Marti in ''China and the Legacy of Deng Xiaoping'', (Brassy's, 2002) p. 19.</ref> सोभियत संघ संगको सम्बन्ध १९८५ मा क्रेमलिनमा [[मिखाइल गोर्बाचोभ|मिखाइल गोर्भाचोब]] पुगेपछि मात्र सुधार भयो र दुई देशको औपचारिक सन्बन्ध १९८९ मा चीन सोभियत शिखर सम्मेलन पछि मात्र पुरानै अवस्थाको झै सुमधुर भयो।<ref>{{Cite web|url=https://www.latimes.com/archives/la-xpm-1989-05-15-mn-141-story.html|title=Gorbachev in China: The Communist Summit : Deng and Gorbachev: Great Reformers Battling Socialist Crises|date=15 May 1989|website=Los Angeles Times|access-date=8 March 2020}}</ref> ====आर्थिक विकासको तीन कदम ==== देङले खुलापनलाई मुख्य नीति बनाई सुधार विकास गरे। उनले ७० वर्ष भित्र चीनको आर्थिक विकासलाई उपयुक्त हुने तीन कदम अघि सारे। पहिलो कदम: १९८० को दशकको अन्त्य सम्ममा १९८० को कुल राष्ट्रिय उत्पादन दोब्बर बनाउने, जनतालाई पर्याप्त खानेकुरा र लुगाफाटो सुनिश्चित गर्ने; दोस्रो कदम, २० औं शताब्दीको अन्त्य सम्ममा १९८० को कुल राष्ट्रिय उत्पादन चार दोब्बर बनाउने, यो लक्ष्य समय भन्दा अगावै १९९५ मा हासिल भयो; तेस्रो कदम, २०५० सम्ममा प्रती व्यक्ति कुल राष्ट्रिय उत्पादन मध्यम विकसित देशको स्तरमा पुर्याउने, जुन स्तरमा, चिनियाँ मानिसले आधुनिकीकरण महसुस गर्नेछन्। <ref>{{cite web|title=The Three-Step Development Strategy|url=http://www.china.org.cn/english/features/38199.htm|url-status=live|archive-url=https://web.archive.org/web/20180917215520/http://www.china.org.cn/english/features/38199.htm|archive-date=17 September 2018|access-date=28 November 2010|publisher=china.org.cn}}</ref> ====अन्य सुधार ==== ===हङकङ तथा मकाउको फिर्ता === [[File:Deng Thatcher 3.JPG|thumb|देङ शियाओ पिङ र बेलायती प्रधानमन्त्री मार्गरेट थ्याचरको १९८४ को वार्ताको प्रतिरुप नमुना, सान्झेन]] १९८० पछि, देङले अर्थतन्त्रको विस्तार, र हङकङ फिर्ताको लागि वार्ताको नेतृत्व गरे उनले बेलायती प्रधानमन्त्री [[मार्गरेट थ्याचर]] सँग व्यक्तिगत रुपमा भेटे। थ्याचर यो वार्ता मा हङकङ टापु र कोव्लून टापूमा बेलायतको शासन निरन्तरता दिने आशाका साथमा सहभागी भएकी थिइन् - तर यो कुरा देङले दृढता पूर्वक अस्वीकार गरे। यो वार्ताको नतिजास्वरुप चीन -बेलायत संयुक्त घोषणापत्र भयो, यसमा १९ डिसेम्बर १९८४ मा हस्ताक्षर भयो, जसमा १९९७ भित्रमा पूरा हङकङ संयुक्त अधिराज्यले चीनलाई फिर्ता गर्ने मार्गचित्र प्रस्तुत गरिएको थियो। चीन सरकारले हस्तान्तरण पछि पचास बर्ष सम्म बेलायती उपनीवेशको आर्थिक प्रणाली र नागरिक स्वतन्त्रताको सम्मान गर्ने सहमत भयो।<ref>Vogel, ''Deng Xiaoping,'' pp. 487–511.</ref><ref>Nancy C. Jackson, "The Legal Regime of Hong Kong After 1997: An Examination of the Joint Declaration of the United Kingdom and the People's Republic of China." ''International Tax & Business Lawyer'' (1987): 377–423. [https://scholarship.law.berkeley.edu/cgi/viewcontent.cgi?referer=https://scholar.google.com/&httpsredir=1&article=1072&context=bjil Online]{{Dead link|date=September 2023 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> चीनको दबाबमा, १९८७ मा पोर्चुगल १९९९ भित्रमा मकाउ फिर्ता सहमत भयो। सन् १९९९ मा पोर्चुगलबाट [[मकाउ]] फिर्ता गराइयो। देङ शियाओ पिङले [[हङकङ]] र [[मकाउ|मकाओ]]लाई शान्तिपूर्ण र व्यवधानरहित ढंगले चीनमा पुन:एकीकरण गराउन विश्वमा नौलो राजनीतिक अवधारणा [[एक देश दुई प्रणाली]] अगाडि सारे। यो सिद्धान्त हङकङ र मकाउको लागि लागू भएपनी, देङको मुख्य लक्ष्य ताइवानका जनतालाई मुख्य भूमीमा जोडिनको लागि आकर्षित गर्नु थियो। ताइवान टापुको सार्वभौमिकतालाई लिएर अझै विवाद कायम छ। <ref>Vogel, ''Deng Xiaoping,'' pp. 477–91.</ref> सन् १९८० मा अगाडि सारिएको त्यो अवधारणाको सार थियो– "भविष्यमा आवश्यक प्रक्रिया पुर्‍याएर एकीकरण गरिने हङकङ र मकाउ एकीकृत चीनको अभिन्न अंग हुनेछन्। चीन एउटै रहने छ तर [[हङकङ]] र [[मकाउ]]मा मुख्य भूमि चीन (मेनल्याण्ड चाइना)को भन्दा फरक व्यवस्था रहने छन्। चीनमा एकीकरण गरिएपछि पनि हङकङ र मकाउमा साविक बमोजिमकै आर्थिक र प्रशासनिक व्यवस्था कायम रहने छन् तथा साविक बमोजिम नै ती स्थानमा अन्तर्राष्ट्रिय व्यापारिक सम्बन्धहरु रहने छन्। " यही अवधारणा बमोजिम चीनको संविधानमै "एक देश दुई प्रणाली" को व्यवस्था गरियो। यसै अनुसार सन् १९८७ मा सन् १९९९ मा पूर्व सन्धी बमोजिम मकाउ चीनलाई हस्तान्तरण हुने गरी [[पोर्तगाल|पोर्चुगल]] सरकारसँग चीनले सम्झौता गर्यो। पुरानै आर्थिक, राजनीतिक, प्रशासनिक प्रणाली र वैदेशिक सम्बन्ध रहने छ भनेर पटक पटक [[पूँजीवाद|पूँजीवादी]] विश्वलाई आश्वस्त गराउने प्रयास गरेपछि सन् १९९७, जुलाई १ का दिन हङकङमा [[चिनियाँ झण्डा]] फहराइयो । === जनसंख्या नियन्त्रण तथा अपराध नियन्त्रण === चीनको तीव्र जनसंख्या वृद्धिबाट समस्याहरू पनि सामु आइरहेको थियो। १९८२ को जनगणना जनसंख्या वृद्धि असामान्य रुपले बढीरहेको र एक अरब नाघेको देखायो। देङले [[हुआ गोफेङ|हुवा गोफेङ]]ले सुरु गरेको "[[एक बच्चा नीति]]" लाई निरन्तरता दिए।<ref>{{Cite web|url=http://www.china-un.ch/eng/bjzl/t176938.htm|title=Family Planning in China|website=www.china-un.ch|url-status=live|archive-url=https://web.archive.org/web/20180619013045/http://www.china-un.ch/eng/bjzl/t176938.htm|archive-date=19 June 2018|access-date=28 November 2019}} {{Webarchive|url=https://web.archive.org/web/20180619013045/http://www.china-un.ch/eng/bjzl/t176938.htm |date=19 June 2018 }}</ref> यो नीति सहरमा लागू गरिएको थियो र यसमा जबर्जस्ती [[गर्भपतन]] समेत सामेल थियो।<ref>Wang Feng, Yong Cai, and Baochang Gu, "Population, policy, and politics: how will history judge China's one-child policy?." ''Population and Development Review'' 38 (2013): 115–129. [http://dragonreport.com/Dragon_Report/Challenges_files/Wang_pp115-129.pdf online] {{Webarchive|url=https://web.archive.org/web/20190606203524/http://dragonreport.com/Dragon_Report/Challenges_files/Wang_pp115-129.pdf |date=6 June 2019 }}</ref> ===थ्यानआनमन चोकको प्रदर्शन दमन === सन् १९८९ मा पूर्वी युरोपका विभिन्न देशहरूमा कम्युनिस्ट शासन ढलिरहेको समयमा, बेइजिङको [[तियानमेन चोक]]मा विद्यार्थीहरू कम्युनिस्ट शासन अन्त्य गर्न १५ अप्रिल देखि ५ जुन १९८९ मा प्रदर्शनमा सहभागी थिए। तर चीनको देङ शासनले ३ र ४ जुनको बीचमा उनीहरुलाई दबाएको थियो। अप्रिल महिनामा सुरु भएको सो आन्दोलन जुन ३ र ४ को बीचमा बेइजिङ नरसंहारमा परिणत भएर अन्त्य भएको थियो। === राजिनामा र १९९२ दक्षिणी भ्रमण === आधिकारिक रुपमा, नोभेम्बर १९८९ मा केन्द्रिय सैन्य परिषदको पदबाट हटेर उच्च ओहोदाबाट निवृत हुने निर्णय गरे। र उनका उत्तराधिकारी जियाङ जमिन केन्द्रिय सैन्य परिषदको नयाँ अध्यक्ष बने।<ref name=":0"/><ref name=":1">{{Cite news| url= https://www.washingtonpost.com/news/monkey-cage/wp/2018/12/19/40-years-ago-deng-xiaoping-changed-china-and-the-world/|title=Analysis {{!}} 40 years ago, Deng Xiaoping changed China—and the world |newspaper=Washington Post |first=Abraham |last=Denmark |language=en |url-status=live |archive-url=https://web.archive.org/web/20190508043643/https://www.washingtonpost.com/news/monkey-cage/wp/2018/12/19/40-years-ago-deng-xiaoping-changed-china-and-the-world/ |archive-date=8 May 2019 |access-date=27 July 2019}}</ref> यद्यपि चीन अझै पनि '''देङ शियाओ पिङ युग'''मा थियो। उनलाई अझै पनि निरन्तर रुपमा देशको "सर्वोच्च नेता" मानिन्थ्यो र शासनमा अझै पनि उनको नियन्त्रण रहेको विश्वास गरिन्थ्यो, र पार्टीको १४ सम्मेलनमा १९९२ मा [[हु जिन्ताओ]]लाई जियाङ जमिनको उत्तराधिकारी नियुक्त गरे। देङलाई आधिकारिक रुपमा "चीनको आर्थिक सुधार र चीनको समाजवादी आधुनिकीकरणको प्रमुख वास्तुकार"को रुपमा मानिन्छ। कम्युनिष्ट पार्टीहरू बीचमा, उनले बूढो उमेरमा पनि राजनीतिबाट सन्यास नलिने कम्युनिस्ट कार्यकर्ताहरूको लागि अनुकरणीय उदाहरण पेश गरेको विश्वास गरिन्छ। नमरेसम्म पद नछाड्ने यस अघिका प्रचलनहरू उनले तोडे र यो परम्परा २०१८ सम्म रह्यो जब [[सि जिनपिङ]]ले पदावधिको सिमा हटाए। उनलाई कुनै उपाधी नजोडी प्रायः ''[[कमरेड]] सियाओ पिङ ''बाट सम्बोधन गरिन्थ्यो। == मृत्यु तथा प्रतिक्रिया == देङको मृत्यु १९ फेब्रुअरी १९९७ मा , ९२ वर्षको उमेरमा फोक्सोको संक्रमण र [[पार्किन्सन]]को कारणले भयो।<ref>{{cite book|title=The Rise of Modern China|last1=Hsü|first1=Immanuel C.Y.|date=2000|publisher=Oxford University Press|isbn=9780195125047|edition=6th|location=New York|page=974|author-link1=Immanuel C. Y. Hsu}}</ref> २४ फेब्रुअरी बिहान १०:०० प्रधानमन्त्री लि पेङले आम जनतालाई तीन मिनेट मौन धारण गर्न आह्वान गरे। राष्ट्रिय झन्डा एक हप्ता सम्म आधा झुकाइयो। सत्तामा उनका उत्तराधिकारी जियाङ जमिनको बलियो पकड भएपनि, सरकारी नीति नियमहरू देङको राजनैतिक तथा आर्थिक सिद्धान्तका आधारमा कायम हुन्थे। देङको मृत्युमा अन्तर्राष्ट्रिय स्तरमा प्रतिक्रिया आयो। [[संयुक्त राष्ट्रसङ्घका महासचिव|संयुक्त राष्ट्र संघका महासचिव]] [[कोफी अन्नान|कोफि अन्नान]]ले देङलाई "अन्तर्राष्ट्रिय समुदायमा देङलाई चीनको आधुनिकीकरण र नाटकीय आर्थिक विकासको रुपमा" स्मरण गरिने बताए। [[फ्रान्सको राष्ट्रपति|फ्रान्सका राष्ट्रपति]] ज्याक्स किर्याकले भने "यो शताब्दीको दौरान, देङ जतिकै, केही थोरै व्यक्तिले विशाल मानव समुदाय गम्भीर परिवर्तनका साथमा नेतृत्व गरेका छन्।" [[संयुक्त अधिराज्यको प्रधानमन्त्री|बेलायती प्रधानमन्त्री]] [[जोन मेजर]]ले हङकङलाई चिनियाँ नियन्त्रणमा फिर्ता गर्नमा देङको प्रमुख भूमिकाको टिप्पणी गरे। क्यानाडाका प्रधानमन्त्री [[जेन क्रिटेन|जिन क्रेटिन]]ले देङलाई चिनियाँ इतिहासमा "निर्णायक व्यक्तित्व" भएको बताए। [[ताइवान]]का कुमिन्ताङ अध्यक्षले पनि शान्ति, सहकार्य, र समृद्धि अभिलाषा व्यक्त गर्दै समवेदना सन्देश पठाए। [[दलाई लामा|दलाइ लामा]]ले तिब्बत मामिलाको प्रश्न नसुझाउदै उनको मृत्यु भएकोमा दु:ख व्यक्त गरे।<ref>[http://www.cnn.com/WORLD/9702/19/deng.world.reax/index.html CNN:World leaders praise Deng's economic legacy] {{Webarchive|url=https://web.archive.org/web/20070816133436/http://www.cnn.com/WORLD/9702/19/deng.world.reax/index.html|date=16 August 2007}} 24 February 1997</ref> ==सन्दर्भ सामग्रीहरू== {{reflist}} [[श्रेणी:चिनियाँ राजनितिज्ञहरू]] [[श्रेणी:कम्युनिष्ट शासक]] [[श्रेणी:सन् १९०४ मा जन्म]] [[श्रेणी:सन् १९९७ मा मृत्यु]] 51yh8jnhhbrpedxhz2ocpw5ybkjwzzz स्पुतनिक-१ 0 97811 1361471 1315677 2026-06-12T09:39:31Z Bishaldev100 28807 1361471 wikitext text/x-wiki [[चित्र:Первый_в_мире_искусственный_спутник_Земли.jpg|अङ्गुठाकार|स्पेस एण्ड मिसाइल टेक्नोलोजीको संग्रहालयमा स्पुतनिक १ को प्रतिकृति ([[सेन्ट पिटर्सवर्ग|सेन्ट-पिटर्सबर्ग]])]] '''स्पुतनिक १''' ({{भाषा-रूसी|Спутник-1}}) [[सोभियत सङ्घ]]द्वारा निर्मित धरतीको पहिलो [[कृत्रिम उपग्रह]] थियो।{{Sfn|Terry|2013|p=233}} यसको प्रक्षेपण सन् १९५७ मा गरिएको थियो। [[सोभियत सङ्घ]]ले यस उपग्रहलाई पृथ्वीको तल्लो कक्षमा ४ अक्टोबर १९५७ मा प्रक्षेपण गरेको थियो। यसले यसको ब्याट्री नसकिएसम्म तीन हप्ता पृथ्वीको परिक्रमा गरेको थियो र दुई महिना पछि [[पृथ्वीको वायुमण्डल]]मा खसेको थियो। ४ जनवरी १९५८ मा स्पुतनिक पृथ्वीको वायुमण्डलमा खसेर जल्नु भन्दा अगाडी पृथ्वीको कक्षमा १४४० चक्कर लगाउँदै करिब {{convert|70|e6km|e6mi|abbr=unit}} दुरी यात्रा गरेको थियो।<ref name="NSSDC">{{cite web|url=https://nssdc.gsfc.nasa.gov/nmc/spacecraft/display.action?id=1957-001B|title=Sputnik 1 – NSSDC ID: 1957-001B|work=NSSDC Master Catalog|publisher=[[नासा]]|archive-url=https://web.archive.org/web/20190708130337/https://nssdc.gsfc.nasa.gov/nmc/spacecraft/display.action?id=1957-001B|archive-date=8 July 2019|access-date=26 March 2008|url-status=live}} {{Webarchive|url=https://web.archive.org/web/20250701050837/https://nssdc.gsfc.nasa.gov/nmc/spacecraft/display.action?id=1957-001B |date=1 July 2025 }}</ref> ==सन्दर्भ सामग्री== {{reflist}} [[श्रेणी:कृत्रिम उपग्रह]] [[श्रेणी:निकिता ख्रुश्चेव]] 3wfj4k3t7qc6v9tbgjur1hqec4oxrlo साम्राज्य 0 99100 1361498 1268630 2026-06-12T11:51:03Z Bishaldev100 28807 1361498 wikitext text/x-wiki '''साम्राज्य''' राष्ट्रहरूको सामूहिक हो, वा अन्य शक्तिशाली [[प्रभुत्व]] वा [[सरकार]] हो। साम्राज्यको क्षेत्र सामान्यतया ठूलो र [[राज्य]] को एक भन्दा अधिक हद सम्म छ। == उच्चारण == sɑːmrɑːd͡ʒjə == इतिहास == === प्रारम्भिक साम्राज्यहरू === === प्रारम्भिक आधुनिक अवधि === === औपनिवेशिक साम्राज्यहरू === === उत्तरार्ध आधुनिक अवधि === == साम्राज्यहरूको पतन == === रोमन साम्राज्य === === उपनिवेशीकरणको अन्त्य === == साम्राज्यबाट संक्रमण == == समकालीन प्रयोग == === संयुक्त राज्य अमेरिका === === युरोपेली संघ === === रूस === <hr> {| class="wikitable sortable" |- ! साम्राज्यहरू |- | [[मङ्गोल साम्राज्य]] |- | [[अटोमन साम्राज्य]] |- | खस साम्राज्य |- | [[मौर्य साम्राज्य]] |- | मराठा साम्राज्य |- |} {{ठुटो|nepali}} [[श्रेणी:संवैधानिक राज्यका प्रकारहरू]] qwzi2yjgiimk4g4w3qz30hfl3us7zr6 २०२६ फिफा विश्वकप 0 100433 1361458 1358561 2026-06-12T08:19:03Z पर्वत सुवेदी 31224 1361458 wikitext text/x-wiki {{छोटो विवरण|उत्तर अमेरिकामा अन्तर्राष्ट्रिय पुरुष फुटबल प्रतियोगिता}} {{Current sport|sport=फुटबल|event=फिफा विश्वकप|date=जुन २०२६}} {{Infobox international football competition | year = २०२६ | tourney_name = फिफा विश्वकप | other_titles = फिफा विश्वकप २६<br>{{native name|es|Copa Mundial de la FIFA 2026}}<br>{{native name|fr|Coupe du Monde de la FIFA 2026}} | image = 2026 FIFA World Cup emblem.svg | size = 250x250px | alt = Emblem of the 2026 FIFA World Cup, showing numbers "2" (top) and "6" (bottom) overlayed by the World Cup trophy <!--Do not add flags to country parameters as per WP:INFOBOXFLAG.--> | country = क्यानडा | country2 = मेक्सिको | country3 = संयुक्त राज्य अमेरिका | dates = जुन ११ – जुलाई १९ | num_teams = ४८ | confederations = ६ | venues = १६ | cities = १६ | champion = | count = | second = | third = | fourth = | matches = {{#invoke:Goalscorers|matches|2026 FIFA World Cup}} | goals = {{#invoke:Goalscorers|goals|2026 FIFA World Cup}} | attendance = {{#invoke:Football attendance summation|main|groups=A-L}} | top_scorer = {{#invoke:Goalscorers|topscorer|2026 FIFA World Cup}} | player = | goalkeeper = | young_player = | fair_play = | prevseason = [[२०२२ फिफा विश्वकप|सन् २०२२]] | nextseason = ''[[२०३० फिफा विश्वकप|सन् २०३०]]'' | updated = {{#invoke:Goalscorers|date|2026 FIFA World Cup|mdy=y}} }} '''२०२६ फिफा विश्वकप''' [[फिफा विश्वकप]]को हालको र २३औँ संस्करण हो, जुन फिफाका सदस्य सङ्घका राष्ट्रिय टोलीहरूद्वारा प्रतिस्पर्धा गरिने चार-चार वर्षमा हुने अन्तर्राष्ट्रिय पुरुष फुटबल प्रतियोगिता हो। यो प्रतियोगिता जुन ११ देखि जुलाई १९, २०२६ सम्म आयोजना भइरहेको छ। यसलाई संयुक्त रूपमा १६ वटा सहरहरू—संयुक्त राज्य अमेरिकामा ११, मेक्सिकोमा ३, र क्यानडामा २ सहरहरूद्वारा आयोजना गरिएको छ।<ref>{{cite news |title=फिफा विश्वकप २०२६: २०२६ फिफा विश्वकप अमेरिका, क्यानडा, र मेक्सिकोमा हुने भएको छ। |url=https://www.bbc.co.uk/sport/football/44464913 |accessdate=१३ जुन २०१८ |publisher=बिबिसी|date=१३ जुन २०१८}}</ref> यो प्रतियोगिता तीन राष्ट्रहरूद्वारा आयोजना गरिएको पहिलो फिफा विश्वकप हो, र अघिल्लो ३२ टोलीहरूबाट विस्तार गरी ४८ टोलीहरू समावेश गरिएको यो पहिलो प्रतियोगिता हो। संयुक्त २०२६ को बोलकबोलले [[मस्को]]मा भएको ६८औँ फिफा कङ्ग्रेसको अन्तिम मतदानमा [[मोरक्को]]को प्रतिस्पर्धी बोलकबोललाई पराजित गरेको थियो। यो [[२००२ फिफा विश्वकप|सन् २००२]] पछि बहु-राष्ट्रहरूद्वारा संयुक्त रूपमा आयोजना हुन लागेको पहिलो विश्वकप हो। यसअघि सन् १९७० र १९८६ का प्रतियोगिताहरू आयोजना गरिसकेको मेक्सिको, तीन पटक विश्वकप आयोजना वा संयुक्त आयोजना गर्ने पहिलो देश बन्नेछ। संयुक्त राज्य अमेरिकाले यसअघि सन् १९९४ मा विश्वकप आयोजना गरेको थियो। यसको विपरित, क्यानडाका लागि भने यो प्रतियोगिता आयोजना वा संयुक्त आयोजना गरेको पहिलो पटक हुनेछ। कतारमा भएको [[२०२२ फिफा विश्वकप|सन् २०२२ को विश्वकप]] विशेष रूपमा नोभेम्बर र डिसेम्बरमा आयोजना भएपछि, यो प्रतियोगिता पुनः आफ्नो परम्परागत [[उत्तरी गोलार्ध]]को ग्रीष्मकालीन तालिकामा फर्किएको छ। आयोजक राष्ट्रका रूपमा [[क्यानडा]], [[मेक्सिको]] र [[संयुक्त राज्य अमेरिका]]का सबै स्वतः छनोट भएका छन्। [[केप भर्ड]], [[कुरासाओ]], [[जोर्डन]] र [[उज्बेकिस्तान]]]ले विश्वकपमा पहिलो पटक प्रतिस्पर्धा गर्नेछन्। अर्जेन्टिना साविकको विजेता हो, जसले सन् २०२२ मा आफ्नो तेस्रो विश्वकप उपाधि जितेको थियो। प्रतियोगिताको तयारीले विवादहरू निम्त्याएको छ, विशेष गरी संयुक्त राज्य अमेरिकाको अध्यागमन र प्रवेशाज्ञा नीतिहरू जसले छनोट भएका टोलीहरू र तिनीहरूका प्रशंसकहरूलाई असर पारेको छ, अमेरिका र इजरायलसँगको जारी युद्धका बीच इरानको सहभागिता, र फिफाद्वारा प्रयोग गरिएको गतिशील टिकट मूल्य निर्धारणलाई लिएर विवाद भएको छ। ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} ==बाह्य कडीहरू== [[श्रेणी:फिफा विश्वकप]] [[श्रेणी:विकिथन-७ मा बनाइएका वा सुधारिएका लेखहरू]] 4l206g6hte7hlk49jqbnnt2fk0zrqoh संयुक्त राज्य अमेरिकाको लागि नेपाली राजदुत 0 101708 1361469 1188313 2026-06-12T09:19:02Z Bishaldev100 28807 1361469 wikitext text/x-wiki {{Infobox official post |post=[[राजदुत]] |body=[[संयुक्त राज्य अमेरिका]]को लागि नेपाली [[नेपाल]] |native_name= |insignia=|insigniasize=120px |insigniacaption=Emblem of Nepal |department= |image= |alt=Embassy of Nepal in Washington, D.C. |incumbent=[[श्रीधर खत्री|श्रीधर खत्री]] |incumbentsince={{dts|2015|05|18}} |style= |residence=Mithan Saray Madhopur Muzaffarpur Bihar |nominator= |nominatorpost= |appointer= |appointerpost= |termlength= |inaugural=[[केशर सम्शेर राणा|केशर सम्शेर]] |formation=1948 / 1953 |last= |abolished= |succession= |deputy= |salary= |website=https://us.nepalembassy.gov.np/ambassador/}} [[वासिङ्टन, डी.सी.]] मा रहने नेपाली राजदुत नेपालका तर्फबाट संयुक्त राज्य अमेरिकाको लागि अधिकारिक प्रतिनिधि हुन्।<ref>{{Cite web|url=http://www.nepalembassyusa.org/|title=Nepal Embassy USA {{!}} Embassy of Nepal USA|website=www.nepalembassyusa.org|language=en-US|accessdate=2017-09-04}} {{Webarchive|url=https://web.archive.org/web/20180108075503/http://www.nepalembassyusa.org/ |date=2018-01-08 }}</ref> == राजदुतको सुची == {| class="wikitable" |Diplomatic agrément |Diplomatic accreditation !राजदुत !नोट ![[नेपालका प्रधानमन्त्रीहरूको सूची|नेपालको प्रधानमन्त्री]] ![[अमेरिकाका राष्ट्रपतिह‍रूको सूची|अमेरिकी राष्ट्रपति]] !पदबदी समाप्त |- |१६-फेब्रुअरी-४८ | | |Legation opened |[[मोहन शमशेर जङ्गबहादुर राणा|मोहन शमशेर]] |[[ह्यारी एस ट्रुम्यान|ह्यारी एस ट्रुम्यान]] | |- |१६-फेब्रुअरी-४८ |१९-फेब्रुअरी-४८ |[[केशर सम्शेर राणा|केशर सम्शेर]] | |[[मोहन शमशेर जङ्गबहादुर राणा|मोहन शमशेर]] |[[ह्यारी एस ट्रुम्यान|ह्यारी एस ट्रुम्यान]] | |- |१९-अगस्ट-४८ | |सुब्बा इश्वरी राज मिश्र |Chargé d'affaires |[[मोहन शमशेर जङ्गबहादुर राणा|मोहन शमशेर]] |[[ह्यारी एस ट्रुम्यान]] | |- |२ १-सेप्टेम्बर-४९ |२७-सेप्टेम्बर-४९ |[[शङ्कर शमशेर जङ्गबहादुर राणा|शङ्कर शमशेर ज.ब.रा.]] |Chargé d'affaires |[[मोहन शमशेर जङ्गबहादुर राणा|मोहन शमशेर]] |[[ह्यारी एस ट्रुम्यान|ह्यारी एस ट्रुम्यान]] | |- |२४-फेब्रुअरी-५३ | | |Legation raised to embassy |[[मातृकाप्रसाद कोइराला|मातृकाप्रसाद कोइराला]] |[[ड्वीट डेभिड आइजेनहावर|ड्वीट डेभिड आइजेनहावर]] | |- |१७-फेब्रुअरी-५३ |२४-फेब्रुअरी-५३ |शङ्कर शमशेर ज.बा.रा. | |[[मातृकाप्रसाद कोइराला|मातृकाप्रसाद कोइराला]] |[[ड्वीट डेभिड आइजेनहावर|ड्वीट डेभिड आइजेनहावर]] | |- |२९-सेप्टेम्बर-५८ |२७-अक्टोबर-५८ |[[ऋषिकेश शाह]] | |[[सुवर्ण शमशेर राणा|सुवर्ण शमशेर राणा]] |[[ड्वीट डेभिड आइजेनहावर|ड्वीट डेभिड आइजेनहावर]] | |- |१३-जुलाई-६१ |३-अगस्ट-६१ |[[मातृकाप्रसाद कोइराला|मातृकाप्रसाद कोइराला]] | |[[तुल्सी गिरी|तुल्सी गिरी]] |[[जोन एफ. केनेडी|जोन एफ केनेडी]] | |- |२३-अक्टोबर-६४ |३-डिसेम्बर-६४ |[[मेजर जनरल]] [[पद्म बहादुर खत्री]] |१९७६– १९८० मा पुनः रजदुत नियुक्त |[[तुल्सी गिरी|तुल्सी गिरी]] |[[लिन्डन बेन्स जोन्सन|लिन्डन बेन्स जोन्सन]] | |- |४-अप्रिल-६९ |१७-अप्रिल-६९ |Kul Shekhar Sharma [id] | |कीर्तिनिधी विष्ट |रिचर्ड निक्सन | |- |२७-अप्रिल-७३ |१४-Jun-७३ |[[यदुनाथ खनाल]] | |[[नगेन्द्रप्रसाद रिजाल|नगेन्द्रप्रसाद रिजाल]] |[[रिचार्ड निक्सन|रिचार्ड निक्सन]] | |- |२५-मे-७५ | |विश्वेश्वर प्रसाद रिमाल |Chargé d'affaires |[[तुल्सी गिरी|तुल्सी गिरी]] |[[जेराल्ड फोर्ड]] | |- |९-जनवरी-७६ |२३-जनवरी-७६ |[[पद्म बहादुर खत्री]] |यस अघि १९६४– १९६९ मा राजदूत भै काम गरेका [[चित्र:Ford,_Nepalese_Ambassador_Padma_Bahadur_Khatri_-_January_23,_1976(Gerald_Ford_Library)(1553344).pdf|thumb|Memorandum of conversation between U.S. President Gerald Ford and the Nepalese Ambassador Padma Bahadur Khatri at the presentation of credentials on २३ जनवरी१९७६|केन्द्र]] |[[तुल्सी गिरी|तुल्सी गिरी]] |Gerald Ford | |- |८-अगस्ट-८० |२९-अगस्ट-८० |[[भेष बहादुर थापा|भेष बहादुर थापा]] | |[[सूर्यबहादुर थापा|सूर्यबहादुर थापा]] |[[जिम्मी कार्टर|जिम्मी कार्टर]] | |- |३-फेब्रुअरी-८६ |१८-फेब्रुअरी-८६ |बिश्व प्रधान | |[[नगेन्द्रप्रसाद रिजाल|नगेन्द्रप्रसाद रिजाल]] |[[रोनाल्ड रेगन|रोनाल्ड रेगन]] | |- |२९-अगस्ट-८८ |१९-सेप्टेम्बर-८८ |हों मान सैंजु | |[[नगेन्द्रप्रसाद रिजाल|नगेन्द्रप्रसाद रिजाल]] |[[रोनाल्ड रेगन|रोनाल्ड रेगन]] | |- |५-Nov-९ १ |२५-Nov-९ १ |योग प्रसाद उपाध्याय | |[[गिरिजाप्रसाद कोइराला|गिरिजा प्रसाद कोइराला]] |[[जर्ज एच डब्लू बुस|जर्ज एच डब्लू बुस]] | |- |७-मार्च-९५ |२०-मार्च-९५ |बासुदेव प्रसाद ढुंगाना | |[[शेरबहादुर देउवा|शेरबहादुर देउवा]] |[[बिल क्लिन्टन|बिल क्लिन्टन]] | |- |१८-मार्च-९६ |३०-अप्रिल-९६ |[[भेष बहादुर थापा|भेष बहादुर थापा]] | |[[शेरबहादुर देउवा|शेरबहादुर देउवा]] |[[बिल क्लिन्टन|बिल क्लिन्टन]] | |- |९-सेप्टेम्बर-९८ |१०-सेप्टेम्बर-९८ |दामोदर प्रसाद गौतम | |[[गिरिजाप्रसाद कोइराला|गिरिजा प्रसाद कोइराला]] |[[बिल क्लिन्टन|बिल क्लिन्टन]] | |- |२८-जनवरी-० २ |१४-फेब्रुअरी-०२ |जय प्रताप राणा |(Died मार्च २००३) |[[ज्ञानेन्द्र वीरविक्रम शाह|ज्ञानेन्द्र शाह]] |[[जर्ज डब्लू बुस|जर्ज डब्लू बुस]] | |- |२०-अगस्ट-०४ |१५-सेप्टेम्बर-०४ |केदार भक्त श्रेष्ठ | |[[शेरबहादुर देउवा|शेरबहादुर देउवा]] |[[जर्ज डब्लू बुस|जर्ज डब्लू बुस]] | |- |२ १-Nov-०७ |२ २-जनवरी-०८ |सुरेश चन्द्र चालिसे |Dr |[[गिरिजाप्रसाद कोइराला|गिरिजा प्रसाद कोइराला]] |[[जर्ज डब्लू बुस|जर्ज डब्लू बुस]] | |- |१८-Nov-०९ |२४-फेब्रुअरी- १० |[[शंकर प्रसाद शर्मा|शंकर प्रसाद शर्मा]] | |[[माधवकुमार नेपाल|माधवकुमार नेपाल]] |[[बाराक ओबामा|बाराक ओबामा]] | |- |१ १-मे- १५ |१८-मे- १५ |[[अर्जुन कार्की|अर्जुन कार्की]] | |[[सुशील कोइराला|सुशील कोइराला]] |[[बाराक ओबामा|बाराक ओबामा]] | |- | | |[[युवराज खतिवडा]] | |[[खड्गप्रसाद ओली]] |[[डोनाल्ड ट्रम्प]] | |- |२०२२ मार्च १२ |२०२२ अप्रिल २२ |श्रीधर खत्री | |[[शेरबहादुर देउवा]] |[[जो बाइडेन]] | |} ==सन्दर्भ सामग्रीहरू== {{reflist}} [[श्रेणी:अमेरिकाको लागि नेपाली राजदुत]] 9yupi0fp79tuyklxs6ojg225uwbcqli 1361470 1361469 2026-06-12T09:22:05Z Bishaldev100 28807 /* राजदुतको सुची */ 1361470 wikitext text/x-wiki {{Infobox official post |post=[[राजदुत]] |body=[[संयुक्त राज्य अमेरिका]]को लागि नेपाली [[नेपाल]] |native_name= |insignia=|insigniasize=120px |insigniacaption=Emblem of Nepal |department= |image= |alt=Embassy of Nepal in Washington, D.C. |incumbent=[[श्रीधर खत्री|श्रीधर खत्री]] |incumbentsince={{dts|2015|05|18}} |style= |residence=Mithan Saray Madhopur Muzaffarpur Bihar |nominator= |nominatorpost= |appointer= |appointerpost= |termlength= |inaugural=[[केशर सम्शेर राणा|केशर सम्शेर]] |formation=1948 / 1953 |last= |abolished= |succession= |deputy= |salary= |website=https://us.nepalembassy.gov.np/ambassador/}} [[वासिङ्टन, डी.सी.]] मा रहने नेपाली राजदुत नेपालका तर्फबाट संयुक्त राज्य अमेरिकाको लागि अधिकारिक प्रतिनिधि हुन्।<ref>{{Cite web|url=http://www.nepalembassyusa.org/|title=Nepal Embassy USA {{!}} Embassy of Nepal USA|website=www.nepalembassyusa.org|language=en-US|accessdate=2017-09-04}} {{Webarchive|url=https://web.archive.org/web/20180108075503/http://www.nepalembassyusa.org/ |date=2018-01-08 }}</ref> == राजदुतको सुची == {| class="wikitable" |Diplomatic agrément |Diplomatic accreditation !राजदुत !नोट ![[नेपालका प्रधानमन्त्रीहरूको सूची|नेपालको प्रधानमन्त्री]] ![[अमेरिकाका राष्ट्रपतिह‍रूको सूची|अमेरिकी राष्ट्रपति]] !पदबदी समाप्त |- |१६-फेब्रुअरी-४८ | | |Legation opened |[[मोहन शमशेर जङ्गबहादुर राणा|मोहन शमशेर]] |[[ह्यारी एस ट्रुम्यान|ह्यारी एस ट्रुम्यान]] | |- |१६-फेब्रुअरी-४८ |१९-फेब्रुअरी-४८ |[[केशर सम्शेर राणा|केशर सम्शेर]] | |[[मोहन शमशेर जङ्गबहादुर राणा|मोहन शमशेर]] |[[ह्यारी एस ट्रुम्यान|ह्यारी एस ट्रुम्यान]] | |- |१९-अगस्ट-४८ | |सुब्बा इश्वरी राज मिश्र |Chargé d'affaires |[[मोहन शमशेर जङ्गबहादुर राणा|मोहन शमशेर]] |[[ह्यारी एस ट्रुम्यान]] | |- |२ १-सेप्टेम्बर-४९ |२७-सेप्टेम्बर-४९ |[[शङ्कर शमशेर जङ्गबहादुर राणा|शङ्कर शमशेर ज.ब.रा.]] |Chargé d'affaires |[[मोहन शमशेर जङ्गबहादुर राणा|मोहन शमशेर]] |[[ह्यारी एस ट्रुम्यान|ह्यारी एस ट्रुम्यान]] | |- |२४-फेब्रुअरी-५३ | | |Legation raised to embassy |[[मातृकाप्रसाद कोइराला|मातृकाप्रसाद कोइराला]] |[[ड्वीट डेभिड आइजेनहावर|ड्वीट डेभिड आइजेनहावर]] | |- |१७-फेब्रुअरी-५३ |२४-फेब्रुअरी-५३ |शङ्कर शमशेर ज.बा.रा. | |[[मातृकाप्रसाद कोइराला|मातृकाप्रसाद कोइराला]] |[[ड्वीट डेभिड आइजेनहावर|ड्वीट डेभिड आइजेनहावर]] | |- |२९-सेप्टेम्बर-५८ |२७-अक्टोबर-५८ |[[ऋषिकेश शाह]] | |[[सुवर्ण शमशेर राणा|सुवर्ण शमशेर राणा]] |[[ड्वीट डेभिड आइजेनहावर|ड्वीट डेभिड आइजेनहावर]] | |- |१३-जुलाई-६१ |३-अगस्ट-६१ |[[मातृकाप्रसाद कोइराला|मातृकाप्रसाद कोइराला]] | |[[तुल्सी गिरी|तुल्सी गिरी]] |[[जोन एफ. केनेडी|जोन एफ केनेडी]] | |- |२३-अक्टोबर-६४ |३-डिसेम्बर-६४ |[[मेजर जनरल]] [[पद्म बहादुर खत्री]] |१९७६– १९८० मा पुनः रजदुत नियुक्त |[[तुल्सी गिरी|तुल्सी गिरी]] |[[लिन्डन बेन्स जोन्सन|लिन्डन बेन्स जोन्सन]] | |- |४-अप्रिल-६९ |१७-अप्रिल-६९ |Kul Shekhar Sharma [id] | |कीर्तिनिधी विष्ट |रिचर्ड निक्सन | |- |२७-अप्रिल-७३ |१४-Jun-७३ |[[यदुनाथ खनाल]] | |[[नगेन्द्रप्रसाद रिजाल|नगेन्द्रप्रसाद रिजाल]] |[[रिचार्ड निक्सन|रिचार्ड निक्सन]] | |- |२५-मे-७५ | |विश्वेश्वर प्रसाद रिमाल |Chargé d'affaires |[[तुल्सी गिरी|तुल्सी गिरी]] |[[जेराल्ड फोर्ड]] | |- |९-जनवरी-७६ |२३-जनवरी-७६ |[[पद्म बहादुर खत्री]] |यस अघि १९६४– १९६९ मा राजदूत भै काम गरेका [[चित्र:Ford,_Nepalese_Ambassador_Padma_Bahadur_Khatri_-_January_23,_1976(Gerald_Ford_Library)(1553344).pdf|thumb|Memorandum of conversation between U.S. President Gerald Ford and the Nepalese Ambassador Padma Bahadur Khatri at the presentation of credentials on २३ जनवरी१९७६|केन्द्र]] |[[तुल्सी गिरी|तुल्सी गिरी]] |Gerald Ford | |- |८-अगस्ट-८० |२९-अगस्ट-८० |[[भेष बहादुर थापा|भेष बहादुर थापा]] | |[[सूर्यबहादुर थापा|सूर्यबहादुर थापा]] |[[जिम्मी कार्टर|जिम्मी कार्टर]] | |- |३-फेब्रुअरी-८६ |१८-फेब्रुअरी-८६ |बिश्व प्रधान | |[[नगेन्द्रप्रसाद रिजाल|नगेन्द्रप्रसाद रिजाल]] |[[रोनाल्ड रेगन|रोनाल्ड रेगन]] | |- |२९-अगस्ट-८८ |१९-सेप्टेम्बर-८८ |हों मान सैंजु | |[[नगेन्द्रप्रसाद रिजाल|नगेन्द्रप्रसाद रिजाल]] |[[रोनाल्ड रेगन|रोनाल्ड रेगन]] | |- |५-Nov-९ १ |२५-Nov-९ १ |योग प्रसाद उपाध्याय | |[[गिरिजाप्रसाद कोइराला|गिरिजा प्रसाद कोइराला]] |[[जर्ज एच डब्लू बुस|जर्ज एच डब्लू बुस]] | |- |७-मार्च-९५ |२०-मार्च-९५ |बासुदेव प्रसाद ढुंगाना | |[[शेरबहादुर देउवा|शेरबहादुर देउवा]] |[[बिल क्लिन्टन|बिल क्लिन्टन]] | |- |१८-मार्च-९६ |३०-अप्रिल-९६ |[[भेष बहादुर थापा|भेष बहादुर थापा]] | |[[शेरबहादुर देउवा|शेरबहादुर देउवा]] |[[बिल क्लिन्टन|बिल क्लिन्टन]] | |- |९-सेप्टेम्बर-९८ |१०-सेप्टेम्बर-९८ |दामोदर प्रसाद गौतम | |[[गिरिजाप्रसाद कोइराला|गिरिजा प्रसाद कोइराला]] |[[बिल क्लिन्टन|बिल क्लिन्टन]] | |- |२८-जनवरी-० २ |१४-फेब्रुअरी-०२ |जय प्रताप राणा |(Died मार्च २००३) |[[ज्ञानेन्द्र वीरविक्रम शाह|ज्ञानेन्द्र शाह]] |[[जर्ज डब्लू बुस|जर्ज डब्लू बुस]] | |- |२०-अगस्ट-०४ |१५-सेप्टेम्बर-०४ |केदार भक्त श्रेष्ठ | |[[शेरबहादुर देउवा|शेरबहादुर देउवा]] |[[जर्ज डब्लू बुस|जर्ज डब्लू बुस]] | |- |२ १-Nov-०७ |२ २-जनवरी-०८ |सुरेश चन्द्र चालिसे |Dr |[[गिरिजाप्रसाद कोइराला|गिरिजा प्रसाद कोइराला]] |[[जर्ज डब्लू बुस|जर्ज डब्लू बुस]] | |- |१८-Nov-०९ |२४-फेब्रुअरी- १० |[[शंकर प्रसाद शर्मा|शंकर प्रसाद शर्मा]] | |[[माधवकुमार नेपाल|माधवकुमार नेपाल]] |[[बाराक ओबामा|बाराक ओबामा]] | |- |१ १-मे- १५ |१८-मे- १५ |[[अर्जुन कार्की|अर्जुन कार्की]] | |[[सुशील कोइराला|सुशील कोइराला]] |[[बाराक ओबामा|बाराक ओबामा]] | |- | | |[[युवराज खतिवडा]] | |[[खड्गप्रसाद ओली]] |[[डोनाल्ड ट्रम्प]] | |- |२०२२ मार्च १२ |२०२२ अप्रिल २२ |श्रीधर खत्री | |[[शेरबहादुर देउवा]] |[[जो बाइडेन]] | |- | | |[[लोकदर्शन रेग्मी]] | | |[[डोनाल्ड ट्रम्प]] | |} ==सन्दर्भ सामग्रीहरू== {{reflist}} [[श्रेणी:अमेरिकाको लागि नेपाली राजदुत]] 7p02tnmehbtjmm2x40zmy70o3kvnbga पर्वत राज्य 0 105955 1361200 1321436 2026-06-12T06:27:38Z Bishaldev100 28807 1361200 wikitext text/x-wiki {{Infobox former country |native_name = पर्वत राज्य |conventional_long_name = १६००० पर्वत राज्य |common_name = पर्वत राज्य |status = राजतन्त्र |era = |event_start = |date_start = |year_start = इ.सं. १४३६ |event_end = इ.सं. १९२९ पश्चात राजा परिचित नगरिएको |date_end = |year_end = इ.सं. १९२९ |event_post = |date_post = |p1 = ताकम राज्य |flag_p1 = Nishankalika Flag of Bagale Thapa clan.svg |p2 = पुला राज्य |flag_p2 = |p3 = ज्यामरूककोट राज्य |flag_p3 = |p4 = राँखु राज्य |flag_p4 = |p5 = |flag_p5 = |p6 = |flag_p6 = |s1 = |s2 = |s3 = |s4 = |s5 = |s6 = |s7 = |s8 = |s9 = |flag_s1 = |flag_s2 = |flag_s3 = |flag_s4 = |flag_s5 = |flag_s6 = |flag_s7 = |flag_s8 = |flag_s9 = |image_flag = |flag_alt = |flag_caption = |image_coat = |symbol_type = |coat_alt = |image_map = |image_map_alt = |image_map_caption = |national_motto = |national_anthem = |capital = [[बेनी नगरपालिका|बेनी]]<br>[[धोरल थाना]]<br> [[ताकम]] (पछिल्लो) |common_languages = [[नेपाली]] र [[मगर भाषा]] |government_type = {{plainlist| * स्वतन्त्र [[राजतन्त्र]]<br><small>(इ. सं. १४३६ – इ. सं. १७८६)</small> * रजौटा<br><small>(इ. सं. १७८६ – इ.सं. १९२९)</small>}} |title_leader = [[राजा]] |leader1 = आनम्म (आनन्दबम/वर्मा) (प्रथम) |year_leader1 = इ. सं. १४३६ - ?? |leader2 = चन्द्रम (चन्द्रबम) (दोस्रो) |year_leader2 = ?? - ?? |leader3 = डिबम/डिम्बबम (तेस्रो) |year_leader3 = ?? |leader4 = कीर्ति बम मल्ल |year_leader4 = ?? |leader5 = पृथ्वी बहादुर मल्ल (अन्तिम) |year_leader5 = - इ.सं.१९२९ |title_deputy = |deputy1 = |year_deputy1 = |deputy2 = |year_deputy2 = |legislature = |house1 = |type_house1 = |stat_year1 = |religion = {{plainlist| * [[हिन्दु धर्म|हिन्दू]] * [[बौद्ध धर्म|बौद्ध]]}} |stat_pop1 = |stat_area1 = |stat_year2 = |stat_pop2 = |stat_area2 = |stat_year4 = |stat_pop4 = |stat_area4 = |currency = |footnotes = |today = {{NEP}} |demonym=|area_km2=|area_rank=|GDP_PPP=|GDP_PPP_year=|HDI=|HDI_year=}} '''पर्वत राज्य''' वा '''१६००० पर्वत राज्य''' एक ऐतिहासिक [[चौबिसी राज्यहरू|चौबिसे राज्य]] थियो । यस राज्यमा पर्बते मल्ल [[ठकुरी]]हरूले राज्य गरेको थिए । यस राज्यको पूर्वज राजा आनन्द बम/वर्मा (स्थानीय लेखोटमा '''आनम्म''') थिए जो [[सल्यान राज्य]]का तेस्रो राजा थिए । उनी खाँडाचक्रका राजा [[मलेबम]] (मलायवर्मा)का वंशज थिए । राजा डिबम/डिम्ब बमले वि.सं. १५४५ मा तक्मेली मगरहरूको सहयोगमा थापा क्षत्रीहरूको [[ताकम राज्य]] यस राज्यमा गाभेका थिए । इ.स. १७८६ मा [[नेपाल अधिराज्य]]मा गाभिएपछि इ.सं. १९२९ सम्म मात्र राजा बनाइयो । वि.सं. २०१७ मा सबै रजौटा उन्मूलन भयो । [[बहादुर शाह]]को नायबीकालमा १८४३ आश्विन १३ मा पर्वतमा नेपालको अधिकार भयो। बागलुङको लडाइँमा केवल ४५ गोर्खाली र २ सय जति पर्वते सैनिक [[वीरगति]] भएपछि कीर्तिबम मल्ल भागे र रियासत छोडिदिए। त्यसपछि पर्वत राज्यमा १९८७ साल सम्म कुनै राजा भएनन्।<ref>{{Cite web |date=२०४१/१२/०९ |title=निर्णय नं. २१९७ - पर्वते रजौटा कायम |url=https://nkp.gov.np/full_detail/5731 |access-date=2026-06-12 |website=नेपाल कानून पत्रिका}}</ref> [[भीम शमशेर जङ्गबहादुर राणा|भीम शम्शेर]]को समयमा देवेन्द्रबहादुर बमलाई पर्वत राजा कायम गरी १९८७।५।१६।२ मा ख.नि. सनद भएको थियो । देवेन्द्रबहादुर बम भीम शम्शेरको नाताकी व्यक्ति नरराजेश्वरी र चन्द्रबहादुर बमका जेठा छोरा थिए। वि.सं. २०१७ मा सबै रजौटा उन्मूलन भयो । ==राजाहरू== पर्वत राज्यका राजाहरूको सूची (ईश्वी सन् मा) : * राजा आनम्म (आनन्द बम/वर्मा) (१४३६ - ??) * राजा चन्द्रम (चन्द्र बम/वर्मा) * राजा डिबम/डिम्ब बम/ डिम्ब राय (??); फ्रान्सिस बुचानन ह्यामिल्टनले डिम्ब भनी लेखेका थिए * राजा नागबममल्ल ( - ??); सन् १४७४ मा दिल्लीका बादशाहको अगाडि मल्ल (पहलमान) युद्घमा दिल्लीका पहलमानलाई जितेका थिए र [[मल्ल]] उपाधि पाएका थिए * राजा पार्वती नारायण मल्ल ( ?? - ) * राजा कीर्ति बम मल्ल ( ??- १७८६); उनको पालामा पर्वत राज्य [[नेपाल अधिराज्य]]मा गाभियो; स्वतन्त्र राज्यका अन्तिम राजा * राजा विजय बहादुर मल्ल (?? ) * राजा चक्र कुमार मल्ल (??) * राजा पृथ्वी बहादुर मल्ल (?? - १९२९) ==अन्य उल्लेखनीय व्यक्तिहरू== * [[मेजर जनरल]] [[प्रदिप प्रताप बम मल्ल]], नेपाली सेनाका रथी, अन्तिम पर्वत राजाको भतिजा ==सन्दर्भ== {{Reflist}} ==बाह्य लिंक== * [http://members.iinet.net.au/~royalty/states/nepal/parbat.html पर्वत राज्य] [[श्रेणी:प्राचीन नेपालका राज्यहरू]] [[श्रेणी:चौबिसी राज्यहरू]] f0a5sqsewqozzs6s0c8flxk5twjqj44 1361201 1361200 2026-06-12T06:36:16Z Bishaldev100 28807 1361201 wikitext text/x-wiki {{Infobox former country |native_name = पर्वत राज्य |conventional_long_name = १६००० पर्वत राज्य |common_name = पर्वत राज्य |status = राजतन्त्र |era = |event_start = |date_start = |year_start = इ.सं. १४३६ |event_end = इ.सं. १९२९ पश्चात राजा परिचित नगरिएको |date_end = |year_end = इ.सं. १९२९ |event_post = |date_post = |p1 = ताकम राज्य |flag_p1 = Nishankalika Flag of Bagale Thapa clan.svg |p2 = पुला राज्य |flag_p2 = |p3 = ज्यामरूककोट राज्य |flag_p3 = |p4 = राँखु राज्य |flag_p4 = |p5 = |flag_p5 = |p6 = |flag_p6 = |s1 = |s2 = |s3 = |s4 = |s5 = |s6 = |s7 = |s8 = |s9 = |flag_s1 = |flag_s2 = |flag_s3 = |flag_s4 = |flag_s5 = |flag_s6 = |flag_s7 = |flag_s8 = |flag_s9 = |image_flag = |flag_alt = |flag_caption = |image_coat = |symbol_type = |coat_alt = |image_map = |image_map_alt = |image_map_caption = |national_motto = |national_anthem = |capital = [[बेनी नगरपालिका|बेनी]]<br>[[धोरल थाना]]<br> [[ताकम]] (पछिल्लो) |common_languages = [[नेपाली]] र [[मगर भाषा]] |government_type = {{plainlist| * स्वतन्त्र [[राजतन्त्र]]<br><small>(इ. सं. १४३६ – इ. सं. १७८६)</small> * रजौटा<br><small>(इ. सं. १७८६ – इ.सं. १९२९)</small>}} |title_leader = [[राजा]] |leader1 = आनम्म (आनन्दबम/वर्मा) (प्रथम) |year_leader1 = इ. सं. १४३६ - ?? |leader2 = चन्द्रम (चन्द्रबम) (दोस्रो) |year_leader2 = ?? - ?? |leader3 = डिबम/डिम्बबम (तेस्रो) |year_leader3 = ?? |leader4 = कीर्ति बम मल्ल |year_leader4 = ?? |leader5 = पृथ्वी बहादुर मल्ल (अन्तिम) |year_leader5 = - इ.सं.१९२९ |title_deputy = |deputy1 = |year_deputy1 = |deputy2 = |year_deputy2 = |legislature = |house1 = |type_house1 = |stat_year1 = |religion = {{plainlist| * [[हिन्दु धर्म|हिन्दू]] * [[बौद्ध धर्म|बौद्ध]]}} |stat_pop1 = |stat_area1 = |stat_year2 = |stat_pop2 = |stat_area2 = |stat_year4 = |stat_pop4 = |stat_area4 = |currency = |footnotes = |today = {{NEP}} |demonym=|area_km2=|area_rank=|GDP_PPP=|GDP_PPP_year=|HDI=|HDI_year=}} '''पर्वत राज्य''' वा '''१६००० पर्वत राज्य''' एक ऐतिहासिक [[चौबिसी राज्यहरू|चौबिसे राज्य]] थियो । यस राज्यमा पर्बते मल्ल [[ठकुरी]]हरूले राज्य गरेको थिए । यस राज्यको पूर्वज राजा आनन्द बम/वर्मा (स्थानीय लेखोटमा '''आनम्म''') थिए जो [[सल्यान राज्य]]का तेस्रो राजा थिए । उनी खाँडाचक्रका राजा [[मलेबम]] (मलायवर्मा)का वंशज थिए । राजा डिबम/डिम्ब बमले वि.सं. १५४५ मा तक्मेली मगरहरूको सहयोगमा थापा क्षत्रीहरूको [[ताकम राज्य]] यस राज्यमा गाभेका थिए । इ.स. १७८६ मा [[नेपाल अधिराज्य]]मा गाभिएपछि इ.सं. १९२९ सम्म मात्र राजा बनाइयो । वि.सं. २०१७ मा सबै रजौटा उन्मूलन भयो । [[बहादुर शाह]]को नायबीकालमा १८४३ आश्विन १३ मा पर्वतमा नेपालको अधिकार भयो। बागलुङको लडाइँमा केवल ४५ गोर्खाली र २ सय जति पर्वते सैनिक [[वीरगति]] भएपछि कीर्तिबम मल्ल भागे र रियासत छोडिदिए। त्यसपछि पर्वत राज्यमा १९८७ साल सम्म कुनै राजा भएनन्।<ref>{{Cite web |date=२०४१/१२/०९ |title=निर्णय नं. २१९७ - पर्वते रजौटा कायम |url=https://nkp.gov.np/full_detail/5731 |access-date=2026-06-12 |website=नेपाल कानून पत्रिका}}</ref> [[भीम शमशेर जङ्गबहादुर राणा|भीम शम्शेर]]को समयमा पृथ्वीबहादुर बमलाई पर्वत राजा कायम गरी १९८७।५।१६।२ मा ख.नि. सनद भएको थियो । पृथ्वीबहादुर बम भीम शम्शेरको नाताकी व्यक्ति चन्द्रकुमारी र चन्द्रबहादुर बमका जेठा छोरा थिए। वि.सं. २०१७ मा सबै रजौटा उन्मूलन भयो । ==राजाहरू== पर्वत राज्यका राजाहरूको सूची (ईश्वी सन् मा) : * राजा आनम्म (आनन्द बम/वर्मा) (१४३६ - ??) * राजा चन्द्रम (चन्द्र बम/वर्मा) * राजा डिबम/डिम्ब बम/ डिम्ब राय (??); फ्रान्सिस बुचानन ह्यामिल्टनले डिम्ब भनी लेखेका थिए * राजा नागबममल्ल ( - ??); सन् १४७४ मा दिल्लीका बादशाहको अगाडि मल्ल (पहलमान) युद्घमा दिल्लीका पहलमानलाई जितेका थिए र [[मल्ल]] उपाधि पाएका थिए * राजा पार्वती नारायण मल्ल ( ?? - ) * राजा कीर्ति बम मल्ल ( ??- १७८६); उनको पालामा पर्वत राज्य [[नेपाल अधिराज्य]]मा गाभियो; स्वतन्त्र राज्यका अन्तिम राजा * राजा विजय बहादुर मल्ल (?? ) * राजा चक्र कुमार मल्ल (??) * राजा पृथ्वी बहादुर मल्ल (?? - १९२९) ==अन्य उल्लेखनीय व्यक्तिहरू== * [[मेजर जनरल]] [[प्रदिप प्रताप बम मल्ल]], नेपाली सेनाका रथी, अन्तिम पर्वत राजाको भतिजा ==सन्दर्भ== {{Reflist}} ==बाह्य लिंक== * [http://members.iinet.net.au/~royalty/states/nepal/parbat.html पर्वत राज्य] [[श्रेणी:प्राचीन नेपालका राज्यहरू]] [[श्रेणी:चौबिसी राज्यहरू]] 6dtptociabubhv9axjqwiez6ifoz453 1361203 1361201 2026-06-12T07:30:20Z Bishaldev100 28807 1361203 wikitext text/x-wiki {{Infobox former country |native_name = पर्वत राज्य |conventional_long_name = १६००० पर्वत राज्य |common_name = पर्वत राज्य |status = राजतन्त्र |era = |event_start = |date_start = |year_start = इ.सं. १४३६ |event_end = इ.सं. १९२९ पश्चात राजा परिचित नगरिएको |date_end = |year_end = इ.सं. १९२९ |event_post = |date_post = |p1 = ताकम राज्य |flag_p1 = Nishankalika Flag of Bagale Thapa clan.svg |p2 = पुला राज्य |flag_p2 = |p3 = ज्यामरूककोट राज्य |flag_p3 = |p4 = राँखु राज्य |flag_p4 = |p5 = |flag_p5 = |p6 = |flag_p6 = |s1 = |s2 = |s3 = |s4 = |s5 = |s6 = |s7 = |s8 = |s9 = |flag_s1 = |flag_s2 = |flag_s3 = |flag_s4 = |flag_s5 = |flag_s6 = |flag_s7 = |flag_s8 = |flag_s9 = |image_flag = |flag_alt = |flag_caption = |image_coat = |symbol_type = |coat_alt = |image_map = |image_map_alt = |image_map_caption = |national_motto = |national_anthem = |capital = [[बेनी नगरपालिका|बेनी]]<br>[[धोरल थाना]]<br> [[ताकम]] (पछिल्लो) |common_languages = [[नेपाली]] र [[मगर भाषा]] |government_type = {{plainlist| * स्वतन्त्र [[राजतन्त्र]]<br><small>(इ. सं. १४३६ – इ. सं. १७८६)</small> * रजौटा<br><small>(इ. सं. १७८६ – इ.सं. १९२९)</small>}} |title_leader = [[राजा]] |leader1 = आनम्म (आनन्दबम/वर्मा) (प्रथम) |year_leader1 = इ. सं. १४३६ - ?? |leader2 = चन्द्रम (चन्द्रबम) (दोस्रो) |year_leader2 = ?? - ?? |leader3 = डिबम/डिम्बबम (तेस्रो) |year_leader3 = ?? |leader4 = कीर्ति बम मल्ल |year_leader4 = ?? |leader5 = पृथ्वी बहादुर मल्ल (अन्तिम) |year_leader5 = - इ.सं.१९२९ |title_deputy = |deputy1 = |year_deputy1 = |deputy2 = |year_deputy2 = |legislature = |house1 = |type_house1 = |stat_year1 = |religion = {{plainlist| * [[हिन्दु धर्म|हिन्दू]] * [[बौद्ध धर्म|बौद्ध]]}} |stat_pop1 = |stat_area1 = |stat_year2 = |stat_pop2 = |stat_area2 = |stat_year4 = |stat_pop4 = |stat_area4 = |currency = |footnotes = |today = {{NEP}} |demonym=|area_km2=|area_rank=|GDP_PPP=|GDP_PPP_year=|HDI=|HDI_year=}} '''पर्वत राज्य''' वा '''१६००० पर्वत राज्य''' एक ऐतिहासिक [[चौबिसी राज्यहरू|चौबिसे राज्य]] थियो । यस राज्यमा पर्बते मल्ल [[ठकुरी]]हरूले राज्य गरेको थिए । यस राज्यको पूर्वज राजा आनन्द बम/वर्मा (स्थानीय लेखोटमा '''आनम्म''') थिए जो [[सल्यान राज्य]]का तेस्रो राजा थिए । उनी खाँडाचक्रका राजा [[मलेबम]] (मलायवर्मा)का वंशज थिए । राजा डिबम/डिम्ब बमले वि.सं. १५४५ मा तक्मेली मगरहरूको सहयोगमा थापा क्षत्रीहरूको [[ताकम राज्य]] यस राज्यमा गाभेका थिए । इ.स. १७८६ मा [[नेपाल अधिराज्य]]मा गाभिएपछि इ.सं. १९२९ सम्म मात्र राजा बनाइयो । वि.सं. २०१७ मा सबै रजौटा उन्मूलन भयो । [[बहादुर शाह]]को नायबीकालमा १८४३ आश्विन १३ मा पर्वतमा नेपालको अधिकार भयो। बागलुङको लडाइँमा केवल ४५ गोर्खाली र २ सय जति पर्वते सैनिक [[वीरगति]] भएपछि कीर्तिबम मल्ल भागे र रियासत छोडिदिए। कम्याण्डर ईनचीफ जनरल [[भीम शमशेर जङ्गबहादुर राणा|भीम शमशेर ज.ब.रा.]]बाट १९६९।२।१० मा पठाएको रूक्का दस्तखतको खाममा भनेकोमा पर्वतका राजा पृथ्वीबहादुर बम मल्लकै भनी संबोधन गरेको देखिन्छ । त्यस खाममा मुलुकी अड्डाको छाप लागेको पाइन्छ ।<ref>{{Cite web |date=२०४१/१२/०९ |title=निर्णय नं. २१९७ - पर्वते रजौटा कायम |url=https://nkp.gov.np/full_detail/5731 |access-date=2026-06-12 |website=नेपाल कानून पत्रिका}}</ref> चन्द्रबहादुर पछि निजका जेठा छोरा पृथ्वीबहादुर बम मल्ल र त्यसपछि निज पृथ्वीबहादुरको जेठा छोरा प्रतिवादी दुर्गाबहादुर बम मल्ल पर्वतका राजा भए। वि.सं. २०१७ मा सबै रजौटा उन्मूलन भयो । ==राजाहरू== पर्वत राज्यका राजाहरूको सूची (ईश्वी सन् मा) : * राजा आनम्म (आनन्द बम/वर्मा) (१४३६ - ??) * राजा चन्द्रम (चन्द्र बम/वर्मा) * राजा डिबम/डिम्ब बम/ डिम्ब राय (??); फ्रान्सिस बुचानन ह्यामिल्टनले डिम्ब भनी लेखेका थिए * राजा नागबममल्ल ( - ??); सन् १४७४ मा दिल्लीका बादशाहको अगाडि मल्ल (पहलमान) युद्घमा दिल्लीका पहलमानलाई जितेका थिए र [[मल्ल]] उपाधि पाएका थिए * राजा पार्वती नारायण मल्ल ( ?? - ) * राजा कीर्ति बम मल्ल ( ??- १७८६); उनको पालामा पर्वत राज्य [[नेपाल अधिराज्य]]मा गाभियो; स्वतन्त्र राज्यका अन्तिम राजा * राजा विजय बहादुर मल्ल (?? ) * राजा चक्र कुमार मल्ल (??) * राजा पृथ्वी बहादुर मल्ल (?? - १९२९) ==अन्य उल्लेखनीय व्यक्तिहरू== * [[मेजर जनरल]] [[प्रदिप प्रताप बम मल्ल]], नेपाली सेनाका रथी, अन्तिम पर्वत राजाको भतिजा ==सन्दर्भ== {{Reflist}} ==बाह्य लिंक== * [http://members.iinet.net.au/~royalty/states/nepal/parbat.html पर्वत राज्य] [[श्रेणी:प्राचीन नेपालका राज्यहरू]] [[श्रेणी:चौबिसी राज्यहरू]] 1g51u8tnxifou0ukvleflf2fiij0lts विदेश नीति 0 119476 1361472 1149793 2026-06-12T10:24:38Z Bishaldev100 28807 /* */ 1361472 wikitext text/x-wiki कुनै देशको '''विदेश [[नीति]] (परराष्ट्र नीति)''', जसलाई विदेशी सम्बन्ध नीति पनि भनिन्छ। यस नीतिकै आधारमा राज्यले आफ्नो राष्ट्रिय हितको रक्षा गर्न र अन्तर्राष्ट्रिय सम्बन्धको वातावरणमा आफ्ना लक्ष्यहरू प्राप्त गर्न छनौट गरेको स्वहितकारी रणनीतिहरूको समूह हुन्छ। एक देशको '''विदेश नीति''' अन्य देशहरूसँग [[अर्थशास्त्र|आर्थिक]], [[राजनीति|राजनीतिक]], सामाजिक र सैन्य विषयहरूमा पालना हुने नीतिहरूको जोड हो। == परिचय == [[श्रेणी:विदेश नीति]] [[श्रेणी:अन्तर्राष्ट्रिय सम्बन्ध]] mnk7e8zh00by270zq25d3vb1a3a5lj8 फेडरल रिजर्भ 0 121215 1361165 1321848 2026-06-11T13:54:39Z Bishaldev100 28807 /* */ 1361165 wikitext text/x-wiki {{Infobox central bank | bank_name_in_local = | image = [[File:Seal of the United States Federal Reserve System.svg|115px]]<br/>फेडरल रिजर्भ सिस्टमको मोहर<br/><br/>[[File:Flag of the United States Federal Reserve.svg|160px]]<br/>फेडरल रिजर्भ सिस्टमको झण्डा | headquarters = [[Eccles Building]], [[वाशिङटन डिसी]], अमेरिका | established = {{Start date and age|p=y|1913|12|23}} | governance = बोर्ड अफ गभर्नर | president = [[केभिन वार्स]] | leader_title = [[फेडरल रिजर्भका अध्यक्ष|अध्यक्ष]] | president2 = [[Lael Brainard]] | leader2_title = उपाध्यक्ष | president3 = [[Michael Barr]] | leader3_title = उपाध्यक्ष | bank_of = [[संयुक्त राज्य अमेरिका]] | ownership = <!-- Before filling in this parameter, please review the talk page discussions regarding the topic. The Federal Reserve's ownership may be too complex to detail in an infobox; the topic is covered in the article body. --> | currency = [[अमेरिकी डलर]] | currency_iso = USD | borrowing_rate = 0.25%<ref name="fed-discount-window">{{cite web|url=https://www.frbdiscountwindow.org/pages/discount-rates/current-discount-rates |title=The Federal Reserve Bank Discount Window & Payment System Risk Website|website=Federal Reserve System|access-date=March 16, 2020}}</ref> <!-- appears as "bank rate" in infobox, should be updated with Discount rate, NOT Federal Funds Rate --> | website = {{Official URL}} | footnotes = | reserve_requirements = [[Reserve requirement#United States|None]]<ref name='fed-zero-rr'>{{cite web|url=https://www.federalreserve.gov/monetarypolicy/reservereq.htm|title=Reserve Requirements|website=Federal Reserve System|access-date=May 10, 2020}}</ref> | interest_rate_target = 0% to 0.25%<ref name="fomc-target">{{cite web|url=http://www.federalreserve.gov/monetarypolicy/openmarket.htm|title=Open Market Operations Archive|website=Federal Reserve System|access-date=March 16, 2020}}</ref><!-- Should be updated with Federal Funds Rate --> | deposit_rate = 0.10%<ref name="interestonreserves">{{cite web|url=http://www.federalreserve.gov/monetarypolicy/reqresbalances.htm|title=Interest on Required Reserve Balances and Excess Balances|website=Federal Reserve System|access-date=March 16, 2020}}</ref> | IOER = Yes | embed = {{Infobox government agency|child=yes |child1_agency = [[Federal Open Market Committee]] |jurisdiction = [[संयुक्त राज्य अमेरिका संघीय सरकार]] |keydocument1 = फेडरल रिजर्भ ऐन}} }} '''फेडरल रिजर्भ''' ({{lang-en|Federal Reserve}} वा फेडरल रिजर्भ सिस्टम वा फेडरल रिजर्भ बैंक वा फेड) संयुक्त राज्य अमेरिकाको [[केन्द्रीय बैङ्क|केन्द्रीय बैंकिङ]] प्रणाली हो। नेपालमा [[नेपाल राष्ट्र बैङ्क|नेपाल राष्ट्र बैंक]]लाई केन्द्रीय बैंक भनिए झै अमेरिकामा केन्द्रीय बैंकलाई फेडरल रिजर्भ बैंक भनिन्छ। फेडरल रिजर्भ बैंकको गठन फेडरल रिजर्भ ऐन अन्तर्गत सन् १९१३ डिसेम्बर २३ दिन [[अमेरिकी काङ्ग्रेस|अमेरिकी कंग्रेस]]ले गरेको थियो। फेडको कार्यालय [[वासिङ्टन डिसी|वाशिङटन डिसी]]मा छ। फेडरल रिजर्भ केन्द्रीय बैंक भएपनि यसले मुद्रा निस्कासनको काम भने गर्दैन । अमेरिकी मुद्रा निस्कासनको काम युनाइटेड स्टेट्स डिपार्टमेन्ट अफ द ट्रेजरीले गर्छ । == काम == === वित्तीय संकट समाधान् === === केन्द्रीय बैंक === [[संयुक्त राज्य अमेरिका|संयुक्त राज्य]]को [[केन्द्रीय बैङ्क|केन्द्रीय बैंक]]को रूपमा आफ्नो भूमिकामा, फेडले बैंकरको बैंक र सरकारी बैंकको रूपमा सेवा गर्दछ। बैंकरको बैंकको रूपमा, यसले भुक्तानी प्रणालीको सुरक्षा र दक्षता सुनिश्चित गर्न मद्दत गर्दछ। === बैंक नियमन === फेडरल रिजर्भले निजी बैंकहरूलाई नियमन गर्दछ। निजीकरण र सरकारी नियमनका प्रतिस्पर्धी विचारहरू बीचको सम्झौताबाट यो प्रणाली डिजाइन गरिएको थियो। ==प्रमुख== {{मुख्य|अमेरिकी केन्द्रीय बैङ्कका अध्यक्ष}} ==यो पनि हेर्नुहोस्== * [[पिपल्स बैंक अफ चाइना]] * [[युरोपेली केन्द्रीय बैङ्क|युरोपेली केन्द्रीय बैंक]] ==सन्दर्भ सामग्रीहरू== {{reflist}} ==बाह्य कडीहरू== * [https://www.federalreserve.gov/aboutthefed.htm आधिकारिक वेवसाइट] [[श्रेणी:केन्द्रीय बैङ्कहरू]] 7q3q9gfsn3zi1jatkdoh392rbj5jf2d जेरोमी पावेल 0 122799 1361167 1320132 2026-06-11T13:58:03Z Bishaldev100 28807 /* */ 1361167 wikitext text/x-wiki {{Infobox officeholder | name = जेरोमी पावेल | native_name = Jerome Powell | image = Jerome H. Powell, Federal Reserve Chair.jpg | caption = सन् २०२२ मा पावेल | office = [[फेडरल रिजर्भका अध्यक्ष|फेडरल रिजर्भ]]का १६औँ अध्यक्ष | president = [[डोनाल्ड ट्रम्प]]<br />[[जो बाइडेन]] | deputy = [[Lael Brainard]]<br />[[Michael Barr]] | term_start = सन् २०१८ फेब्रुअरी ५ | term_end = २०२६ मे २२ | predecessor = [[जेनेट एलन]] | successor = [[केभिन वार्स]] | birth_name = जेरोमी हेडन पावेल | birth_date = {{birth date and age|1953|2|4}} | birth_place = [[वासिङ्टन डिसी|वासिङ्टन, डी.सी.]], संयुक्त राज्य | death_date = | death_place = | party = [[रिपब्लिकन पार्टी (अमेरिका)|रिपब्लिकन]]<ref name=nominate>{{cite news | url=https://www.nytimes.com/2011/12/28/business/economy/obama-to-nominate-economics-professor-and-ex-treasury-official-to-fed-board.html | title=Obama to Nominate Two for Vacancies on Fed Board |first=Binyamin | last=Applebaum | work=The New York Times | date=December 27, 2011}}</ref><ref name=nominate/> | spouse = {{marriage|एलिसा लियोनार्ड|September 14, 1985}} | children = ३ | education = [[प्रिन्सटन विश्वविद्यालय]] ([[कला स्नातक|बी.ए.]])<br/>[[Georgetown University]] ([[Juris Doctor|JD]]) | net_worth = $५५ मिलियन<ref name=richest>{{cite news |url=https://www.washingtonpost.com/news/wonk/wp/2017/10/31/jerome-powell-trumps-pick-to-lead-fed-would-be-the-richest-chair-since-the-1940s/ | title=Jerome Powell, Trump's pick to lead Fed, would be the richest chair since the 1940s | first=Heather | last=Long |work=[[The Washington Post]] | date=October 31, 2017}}</ref><ref name=wealthy>{{cite news |url=https://www.bloomberg.com/gadfly/articles/2017-11-02/jerome-powell-at-the-fed-is-trump-s-kind-of-wealthy | title=Powell Is Trump's Kind of Rich | first=Stephen | last=Gandel | work=[[Bloomberg L.P.]] | date=November 2, 2017}}</ref><ref>Public Financial Disclosure Report (OGE Form 2783) Executive Branch Personnel, U.S. Office of Government Ethics. Annual Report 2017: Powell, Jerome. https://extapps2.oge.gov/201/Presiden.nsf/PAS+Index/E54DC5C9281668888525815A006BF4E1/%24FILE/Jerome-H-Powell-2017-278.pdf {{Webarchive|url=https://web.archive.org/web/20210812134911/https://extapps2.oge.gov/201/Presiden.nsf/PAS+Index/E54DC5C9281668888525815A006BF4E1/%24FILE/Jerome-H-Powell-2017-278.pdf |date=2021-08-12 }} ''Accessed April 24, 2020.''</ref>फेडरल रिजर्भका गभरर्नरहरू मध्ये उनी सबैभन्दा धनी सदस्य हुन्।<ref>{{cite news | url=https://www.wsj.com/articles/SB10000872396390443589304577635702418120554 | title=Newest Fed Governor Is Board's Richest Member | first1=Kristina | last1=Peterson | first2=Sarah | last2=Portlock | work=[[The Wall Street Journal]] | date=September 6, 2012 | url-access=subscription}}</ref><ref name=richest/><ref name=wealthy/> }} '''जेरोमी हेडेन पावेल''' (जन्म १९५३ फेब्रुअरी ४), जसलाई "जे" को नामले पनि चिनिन्छ,<ref>{{Cite web|url=https://www.bloomberg.com/profile/person/15046536|title=Bloomberg - Jay Powell, Federal Reserve System: Profile and Biography|website=www.bloomberg.com|accessdate=2021-08-12}}</ref> [[फेडरल रिजर्भका अध्यक्ष|फेडरल रिजर्भका १६औँ अध्यक्ष]] हुन्, उनी सन् २०१८ फेब्रुअरी देखि सो कार्यभार सम्हालिरहेका छन्। उनलाई सन् २०१२ मा तत्कालिन अमेरिकी [[अमेरिकाको राष्ट्रपति|राष्ट्रपति]] [[बाराक ओबामा|बराक ओबामा]]ले बोर्ड अफ गभर्नरमा मनोनयन गरेका थिए, र पछि अध्यक्षको रूपमा राष्ट्रपति [[डोनाल्ड ट्रम्प]]द्वारा मनोनित भएका थिए, दुवै मामिलामा [[अमेरिकी सिनेट|संयुक्त राज्य सिनेट]]द्वारा उनको मनोनयन अनुमोदन भएको थियो।<ref>{{Cite news|url=https://www.npr.org/sections/thetwo-way/2018/01/23/580157250/senate-confirms-jerome-powell-as-new-federal-reserve-chair|title=Senate Confirms Jerome Powell As New Federal Reserve Chair|work=[[NPR]]|access-date=January 31, 2018}}</ref><ref>{{Cite news|url=http://thehill.com/policy/finance/370329-senate-confirms-jerome-powell-as-fed-chairman|title=Senate confirms Jerome Powell as Fed chairman|last=The Hill|access-date=January 31, 2018}}{{Cite news|url=https://www.federalreserve.gov/newsevents/pressreleases/monetary20180131c.htm|title=Federal Open Market Committee unanimously selects Jerome H. Powell to serve as its Chairman, effective February 3, 2018|last=The Federal Reserve|access-date=February 2, 2018}}</ref> ==जीवनी== ==यो पनि हेर्नुहोस्== * [[२०२० सेयर बजार क्र्यास|२०२० शेयर बजार क्र्यास]] * [[चीन–अमेरिका व्यापार युद्ध]] * [[कोभिड-१९ आर्थिक मन्दी]] * [[फेड मोडल]] * [[कोभिड -१९ महामारीको वित्तीय बजारमा प्रभाव]] ==सन्दर्भ सामग्रीहरू== {{reflist}} {{कमन्सश्रेणी|Jerome Powell}} {{प्राधिकरण नियन्त्रण}} [[श्रेणी:अमेरिकी केन्द्रीय बैङ्कका अध्यक्षहरू]] [[श्रेणी:जीवित मानिसहरू]] [[श्रेणी:सन् १९५३ मा जन्म]] jqbef97hlwxql5c846k391oppp79ouy ढाँचा:Year Nobel Prize winners 10 123142 1361198 1038816 2026-06-12T06:06:09Z Bishaldev100 28807 1361198 wikitext text/x-wiki {{#invoke:navbox|navbox | name = {{{year|Year}}} Nobel Prize winners | title = {{{year}}} [[Nobel Prize]] laureates | state = {{{state|autocollapse}}} | bodyclass = hlist | group1 = [[रसायन शास्त्रमा नोबेल पुरस्कार|रसायन]] | list1 = {{{chemistry|}}} | group2 = [[साहित्यमा नोबेल पुरस्कार|साहित्य]] | list2 = {{{literature|}}} | group3 = [[शान्तिमा नोबेल पुरस्कार|शान्ति]] {{#ifexist:{{{year}}} Nobel Peace Prize|{{#if:{{#invoke:redirect|isRedirect|{{{year}}} Nobel Peace Prize}}|<!-- If it's a redirect then it probably redirects to an already linked winner so don't use the redirect -->|([[{{{year}}} Nobel Peace Prize|{{{year}}}]])}}}} | list3 = {{{peace|}}} | group4 = [[भौतिक शास्त्रमा नोबेल पुरस्कार|भौतिक शास्त्र]] | list4 = {{{physics|}}} | group5 = [[क्रिया विज्ञान तथा चिकित्सामा नोबेल पुरस्कार|चिकित्सा]] | list5 = {{{medicine|}}} | group6 = [[अर्थशास्त्रमा नोबेल पुरस्कार|अर्थशास्त्र]] | list6 = {{{economy|}}} | below = {{{below|}}}{{Nobel Prize winners footer|{{{year|}}}}} }}{{#ifeq:{{FULLPAGENAME}}|Template:{{{year|}}} Nobel Prize winners| {{collapsible option}} [[Category:Nobel Prize templates]] }}<noinclude> {{Documentation}} </noinclude> kgplobkeur57c7oj5wpf4a3lbqnbzie ढाँचा:२०२० नोबेल पुरस्कार विजेताहरू 10 123143 1361199 1038817 2026-06-12T06:06:53Z Bishaldev100 28807 1361199 wikitext text/x-wiki {{Year Nobel Prize winners |year = २०२० |state = {{{state|}}} |chemistry = *[[Emmanuelle Charpentier]] (फ्रान्स) *[[Jennifer Doudna]] (United States) |literature = [[Louise Glück]] (संयुक्त राज्य) |peace = [[विश्व खाद्य कार्यक्रम]] |physics = *[[Roger Penrose]] (संयुक्त अधिराज्य) *[[Reinhard Genzel]] (जर्मनी) *[[Andrea M. Ghez]] (संयुक्त राज्य) |medicine = *[[Harvey J. Alter]] (संयुक्त राज्य) *[[Michael Houghton (virologist)|Michael Houghton]] (संयुक्त अधिराज्य) *[[Charles M. Rice]] (संयुक्त राज्य) |economy = *[[पल मिलग्रोम]] (संयुक्त राज्य) *[[Robert B. Wilson]] (संयुक्त राज्य) }}<noinclude> '''Source''': https://www.nobelprize.org/, retrieved 6 October 2020. <noinclude> {{collapsible option}} [[Category:नोबेल पुरस्कार]] </noinclude> 9ww9skir4s60p1tqikqdxmoxk19blng मोड्युल:Flagg/Altvar data 828 123452 1361465 1042674 2026-06-12T08:50:42Z पर्वत सुवेदी 31224 1361465 Scribunto text/plain local p = {} function p.alttable(age) local alt_map = { ["af"]={altlink="national American football team";altvar="American football"}; ["afu"]={altlink="national junior American football team";altvar="American football"}; ["afw"]={altlink="women's national American football team";altvar="American football"}; ["arf"]={altlink="national Australian rules football team";altvar="Australian rules football";mw="men's"}; ["arfw"]={altlink="women's national Australian rules football team";altvar="Australian rules football";mw="women's"}; ["bandy"]={altlink="national bandy team";altvar="bandy"}; ["bandyw"]={altlink="women's national bandy team";altvar="bandy";template="bandyW"}; ["bb"]={altlink="national baseball team";altvar="baseball"}; ["bbstate"]={altlink="state baseball team";altvar="baseball";template="bb-state"}; ["bbw"]={altlink="women's national baseball team";altvar="baseball"}; ["bd"]={altlink="national badminton team";altvar="badminton"}; ["bs"]={altlink="national beach soccer team";altvar="beach soccer";template="beachsoccer"}; ["bsw"]={altlink="women's national beach soccer team";altvar="women's beach soccer";template="beachsoccerwomen"}; ["bh"]={altlink="national beach handball team";altvar="beach handball"}; ["bhw"]={altlink="women's national beach handball team";altvar="beach handball";mw="women's"}; ["bk"]={altlink="national basketball team";altvar="basketball"}; ["bku"]={altlink="men's national under-"..age.." basketball team";altvar="basketball";age="under-"..age}; ["bkw"]={altlink="women's national basketball team";altvar="basketball";mw="women's"}; ["bkwu"]={altlink="women's national under-"..age.." basketball team";altvar="basketball";mw="women's";age="under-"..age}; ["cr"]={altlink="national cricket team";altvar="cricket"}; ["cr19"]={altlink="national under-19 cricket team";altvar="cricket";age="Under-19"}; ["crw"]={altlink="national women's cricket team";altvar="cricket";mw="women's"}; ["davis"]={altlink="Davis Cup team";altvar="tennis";mw="Davis"}; ["fb"]={altlink="राष्ट्रिय फुटबल टोली";altvar="football"}; ["fba"]={altlink="football association";altvar="football"}; ["fbl"]={altlink="A' national football team";altvar="football";mw="A'"}; ["fbm"]={altlink="military national football team";altvar="football"}; ["fbo"]={altlink="Olympic football team";altvar="football";mw="Olympic"}; ["fbu"]={altlink="national under-"..age.." football team";altvar="football";age="under-"..age}; ["fbw"]={altlink="महिला राष्ट्रिय फुटबल टोली";altvar="football";mw="women's"}; ["fbwm"]={altlink="women's military national football team";altvar="football";mw="women's"}; ["fbwu"]={altlink="women's national under-"..age.." football team";altvar="football";mw="women's";age="under-"..age}; ["fed"]={altlink="Fed Cup team";altvar="tennis";mw="Fed"}; ["fhm"]={altlink="men's national field hockey team";altvar="field hockey";mw="men's"}; ["fhw"]={altlink="women's national field hockey team";altvar="field hockey";mw="women's"}; ["fl"]={altlink="men's national floorball team";altvar="floorball";mw="men's"}; ["flu"]={altlink="men's national under-19 floorball team";altvar="floorball";mw="men's";age="under-19"}; ["flw"]={altlink="women's national floorball team";altvar="floorball";mw="women's"}; ["flwu"]={altlink="women's national under-19 floorball team";altvar="floorball";mw="women's";template="flw19"}; ["fsw"]={altlink="women's national futsal team";altvar="futsal";mw="women's"}; ["fs"]={altlink="national futsal team";altvar="futsal";template="futsal"}; ["gb"]={altlink="men's national goalball team";altvar="goalball";mw="men's"}; ["gbw"]={altlink="women's national goalball team";altvar="goalball";mw="women's"}; ["hb"]={altlink="national handball team";altvar="handball"}; ["hbj"]={altlink="national junior handball team";altvar="handball"}; ["hbw"]={altlink="women's national handball team";altvar="handball";mw="women's"}; ["hbwj"]={altlink="women's junior national handball team";altvar="handball"}; ["hbwy"]={altlink="women's youth national handball team";altvar="handball";mw="women's"}; ["hby"]={altlink="national youth handball team";altvar="handball"}; ["hopman"]={altlink="at the Hopman Cup";altvar="tennis";mw="Hopman"}; ["iflm"]={altlink="men's national lacrosse team";altvar="lacrosse";mw="men's"}; ["iflw"]={altlink="women's national lacrosse team";altvar="lacrosse";mw="women's"}; ["iflwu"]={altlink="women's national under-19 lacrosse team";altvar="lacrosse";mw="women's";template="iflwu19"}; ["ih"]={altlink="men's national ice hockey team";altvar="ice hockey";mw="men's"}; ["ih18"]={altlink="men's national under-18 ice hockey team";altvar="ice hockey";mw="men's";age="under-18"}; ["ihj"]={altlink="men's national junior ice hockey team";altvar="ice hockey";mw="men's";age="junior"}; ["ihw"]={altlink="women's national ice hockey team";altvar="ice hockey";mw="women's"}; ["ihw18"]={altlink="women's national under-18 ice hockey team";altvar="ice hockey";mw="women's";age="U-18"}; ["iih"]={altlink="men's national inline hockey team";altvar="inline hockey"}; ["iihj"]={altlink="men's national junior inline hockey team";altvar="inline hockey";mw="junior"}; ["iihw"]={altlink="women's national inline hockey team";altvar="inline hockey";mw="women's"}; ["iil"]={altlink="national indoor lacrosse team";altvar="lacrosse";mw="men's"}; ["ish"]={altlink="men's national ice sledge hockey team";altvar="sledge hockey"}; ["kd"]={altlink="national kabaddi team";altvar="Kabaddi"}; ["korf"]={altlink="national korfball team";altvar="korfball"}; ["nb"]={altlink="national netball team";altvar="netball"}; ["p&p"]={altlink="men's national pitch and putt team";altvar="pitch and putt"}; ["rhm"]={altlink="national roller hockey team";altvar="roller hockey";mw="men's"}; ["rhw"]={altlink="women's national roller hockey team";altvar="roller hockey";mw="women's"}; ["rl"]={altlink="national rugby league team";altvar="rugby league"}; ["rollerderby"]={altlink="national roller derby team";altvar="roller derby";template="RollerDerby"}; ["ru"]={altlink="national rugby union team";altvar="rugby union"}; ["ru7"]={altlink="national rugby union team (sevens)";altvar="rugby sevens"}; ["ru7w"]={altlink="women's national rugby union team (sevens)";altvar="rugby sevens";mw="women's"}; ["rua"]={altlink="A national rugby union team";altvar="rugby union-a";template="ruA"}; ["ruu"]={altlink="national under-"..age.." rugby union team";altvar="rugby union";age="under-"..age}; ["ruw"]={altlink="women's national rugby union team";altvar="rugby union";mw="women's"}; ["sb"]={altlink="men's national softball team";altvar="softball";mw="men's"}; ["sbw"]={altlink="women's national softball team";altvar="softball";mw="women's"}; ["speedway"]={altlink="national speedway team";altvar="speedway"}; ["speedwaylt"]={altlink="national long track team";altvar="long track";template="speedwayLT"}; ["svb"]={altlink="men's national sitting volleyball team";altvar="sitting volleyball";mw="men's"}; ["svbw"]={altlink="women's sitting national volleyball team";altvar="sitting volleyball";mw="women's"}; ["vb"]={altlink="men's national volleyball team";altvar="volleyball";mw="men's"}; ["vbw"]={altlink="women's national volleyball team";altvar="volleyball";mw="women's"}; ["wbk"]={altlink="men's national wheelchair basketball team";altvar="wheelchair basketball"}; ["wbkw"]={altlink="women's national wheelchair basketball team";altvar="wheelchair basketball";mw="women's"}; ["whr"]={altlink="national wheelchair rugby team";altvar="wheelchair rugby"}; ["wightman"]={altlink="Wightman Cup team";altvar="tennis";mw="Wightman"}; ["wp"]={altlink="men's national water polo team";altvar="water polo"}; ["wpw"]={altlink="women's national water polo team";altvar="water polo";mw="women's"}; ["airforce"]={altlink="Air Force";altvar="air force";template="air force"}; ["army"]={altlink="Army";altvar="army"}; ["navy"]={altlink="Navy";altvar="naval"} } local alt_aliases = { ["a'football"]="fbl"; ["americanfootball"]="af"; ["australianrulesfootball"]="arf"; ["badminton"]="bd"; ["baseball"]="bb"; ["baseballstate"]="bbstate"; ["beachhandball"]="bh"; ["beachsoccer"]="bs"; ["beachsoccerwomen"]="bsw"; ["basketball"]="bk"; ["cricket"]="cr"; ["daviscup"]="davis"; ["fedcup"]="fed"; ["football"]="fb"; ["footballassociation"]="fba"; ["fh"]="fhm"; ["fieldhockey"]="fhm"; ["fl19"]="flu"; ["floorball"]="fl"; ["flw19"]="flwu"; ["flwu19"]="flwu"; ["futsal"]="fs"; ["goalball"]="gb"; ["handball"]="hb"; ["hopmancup"]="hopman"; ["icehockey"]="ih"; ["icesledgehockey"]="ish"; ["iflwu19"]="iflwu"; ["indoorlacrosse"]="iil"; ["inlinehockey"]="iih"; ["junioramericanfootball"]="afu"; ["juniorhandball"]="hbj"; ["junioricehockey"]="ihj"; ["juniorinlinehockey"]="iihj"; ["kabaddi"]="kd"; ["korfball"]="korf"; ["lacrosse"]="iflm"; ["men'sfieldhockey"]="fhm"; ["men'slacrosse"]="iflm"; ["militaryfootball"]="fbm"; ["netball"]="nb"; ["olympicfootball"]="fbo"; ["pitchandputt"]="p&p"; ["rollerhockey"]="rhm"; ["rugbyleague"]="rl"; ["rugbysevens"]="ru7"; ["rugbyunion"]="ru"; ["rugbyuniona"]="rua"; ["rugbyunionsevens"]="ru7"; ["softball"]="sb"; ["longtrack"]="speedwaylt"; ["sittingvolleyvall"]="svb"; ["under18icehockey"]="ih18"; ["under19cricket"]="cr19"; ["volleyball"]="vb"; ["waterpolo"]="wp"; ["wheelchairbasketball"]="wbk"; ["wheelchairrugby"]="whr"; ["wightmancup"]="wightman"; ["women'samericanfootball"]="afw"; ["women'saustralianrulesfootball"]="arfw"; ["women'sbandy"]="bandyw"; ["women'sbaseball"]="bbw"; ["women'sbasketball"]="bkw"; ["women'sbeachhandball"]="bhw"; ["women'sbeachsoccer"]="bsw"; ["women'scricket"]="crw"; ["women'sfieldhockey"]="fhw"; ["women'sfloorball"]="flw"; ["women'sfootball"]="fbw"; ["women'sfutsal"]="fsw"; ["women'sgoalball"]="gbw"; ["women'shandball"]="hbw"; ["women'sicehockey"]="ihw"; ["women'sinlinehockey"]="iihw"; ["women'srollerhockey"]="rhw"; ["women'sunder18icehockey"]="ihw18"; ["women'sjuniorhandball"]="hbwj"; ["women'slacrosse"]="iflw"; ["women'smilitaryfootball"]="fbwm"; ["women'srugbysevens"]="ru7w"; ["women'srugbyunion"]="ruw"; ["women'srugbyunionsevens"]="ru7w"; ["women'ssittingvolleyvall"]="svbw"; ["women'ssoftball"]="sbw"; ["women'svolleyball"]="vbw"; ["women'swaterpolo"]="wpw"; ["women'swheelchairbasketball"]="wbkw"; ["women'syouthbasketball"]="bkwu"; ["women'syouthfootball"]="fbwu"; ["women'syouthhandball"]="hbwy"; ["youthbasketball"]="bku"; ["youthcricket"]="cr19"; ["youthfootball"]="fbu"; ["youthhandball"]="hby"; ["youthrugbyunion"]="ruu" } return alt_map, alt_aliases end function p.list_all(frame) --Load data local alt_map, alt_aliases = p.alttable("''<span style=\"color:green;\">age</span>''") --Add aliases to map table for k,v in pairs(alt_map) do alt_map[k].aliases = {} end local wrong_aliases = {} table.sort(alt_aliases) for k,v in pairs(alt_aliases) do if alt_map[v] then table.insert(alt_map[v].aliases,k) else table.insert(wrong_aliases,k) end end --Create html table & header row local list = mw.html.create("table") list:addClass("wikitable sortable collapsible") local head = list:tag("tr") head:tag("th"):wikitext("Code") head:tag("th"):wikitext("Aliases") head:tag("th"):wikitext("Altlink (suffix)") head:tag("th"):wikitext("Altvar") head:tag("th"):wikitext("Template") --Append rows to create table body table.sort(alt_map) for k,v in pairs(alt_map) do local row = list:tag("tr") local temp = alt_map[k].template or k row:tag("td"):wikitext("<code>"..k.."</code>") row:tag("td"):wikitext("<code>"..table.concat(alt_map[k].aliases,"</code><br/><code>").."</code>") row:tag("td"):wikitext(alt_map[k].altlink) row:tag("td"):wikitext(alt_map[k].altvar) row:tag("td"):wikitext("[[Template:"..temp.."|"..temp.."]]") end if #wrong_aliases > 0 then local wrong_list = "These aliases point to non-existing data: <code>"..table.concat(wrong_aliases,"</code> <code>").."</code>" list:tag("tr"):tag("td"):attr("colspan","4"):css("color","red"):wikitext(wrong_list) end return list end return p cl9e6mjfth3w75mskx7uo0jlxpshb8x ध्वजावाहक 0 133588 1361163 1348037 2026-06-11T13:48:03Z Bishaldev100 28807 /* ध्वजा बाहक एयरलाइन्सहरूको सूची */ 1361163 wikitext text/x-wiki [[चित्र:Aerospatiale-British_Aerospace_Concorde_102,_British_Airways_AN0744492.jpg|अङ्गुठाकार| कन्कोर्ड, [[संयुक्त अधिराज्य|युनाइटेड किंगडमको]] ध्वजावाहक ।]] '''ध्वजा वाहक''' भनेको [[वायुसेवा|एयरलाइन]] वा ढुवानी कम्पनी जस्ता यातायात कम्पनी हो, जुन स्थानीय रूपमा [[सार्वभौम राज्य|सार्वभौम राज्यमा]] दर्ता भएको हुन्छ र, सरकारले अन्तर्राष्ट्रिय सञ्चालनका लागि प्रदान गरेको अधिमान्य अधिकार वा विशेषाधिकारहरू प्राप्त गर्दछ। ऐतिहासिक रूपमा, यो शब्दावली कुनै पनि देशको सरकारको स्वामित्वमा रहेको र त्यो देशको राष्ट्रिय पहिचानसँग सम्बन्धित एयरलाइन्सलाई जनाउन प्रयोग गरिन्थ्यो। <ref>{{Cite news|url=https://www.telegraph.co.uk/travel/travel-truths/flag-carriers-death-of-legacy-airlines-air-france/|title=The slow death of the flag carrier: Could state-owned airlines become a thing of the past?|last=Morris|first=Hugh|date=17 March 2019|work=The Telegraph|archive-url=https://ghostarchive.org/archive/20220112/https://www.telegraph.co.uk/travel/travel-truths/flag-carriers-death-of-legacy-airlines-air-france/|archive-date=12 January 2022|language=en-GB|quote=Malaysia is the latest nation to see its flag carrier – a label that in times gone by indicated a government-owned airline, and one that embodied a country’s national identity – teeter on the brink.}}</ref> यस्तो एयरलाइनलाई '''राष्ट्रिय वायुसेवा''' वा '''राष्ट्रिय वाहकको''' रूपमा पनि चिनिन्छ, यद्यपि केही देशहरूमा यसको फरक कानूनी अर्थ हुन सक्छ। आजको समयमा, ध्वजावाहक भनेको गृह देशसँग बलियो सम्बन्ध भएको वा जसले आफ्नो गृह देशलाई अन्तर्राष्ट्रिय रूपमा प्रतिनिधित्व गर्ने कुनै पनि अन्तर्राष्ट्रिय एयरलाइन हो , चाहे त्यो सरकारी स्वामित्वको होस् वा नहोस्। <ref>{{Cite web |last=McMurtry |first=Ian |date=25 May 2018 |title=Palestinian Airlines: The Homeless Flag Carrier |url=https://airlinegeeks.com/2018/05/25/palestinian-airlines-the-homeless-flag-carrier/ |access-date=12 June 2019 |website=AirlineGeeks.com |language=en-US}}</ref> <ref>{{Cite web |last=Moores |first=Victoria |date=24 May 2019 |title=Interview: CEO aims to make Virgin Atlantic UK's second flag carrier |url=https://atwonline.com/airlines/interview-ceo-aims-make-virgin-atlantic-uk-s-second-flag-carrier |access-date=12 June 2019 |website=atwonline.com |language=en}}</ref> == पृष्ठभूमि == "ध्वजा वाहक" शब्द त्यो समयको लिगेसी हो जतिबेला [[देश|देशहरूले]] राज्यको स्वामित्वका एयरलाइन कम्पनीहरू स्थापना गर्थे। एयरलाइन्स स्थापना र सञ्चालनको लागि उच्च पूँजी लागतका कारण त्यतिबेला सरकारले एयरलाइन्स कम्पनी स्थापना नेतृत्व लिन्थे। यद्यपि, त्यस्ता सबै एयरलाइन्स सरकारी स्वामित्वका थिएनन्; प्यान एम, TWA, क्याथे प्यासिफिक, Union de Transports Aériens, Canadian Pacific Airlines र Olympic Airlines सबै निजी स्वामित्वमा थिए। यी मध्ये अधिकांशलाई ध्वजा वाहक मानिन्थ्यो <ref>{{Cite news|title=Airline Management; Strategies for the 21st Century|last=Paul Stephen Dempsey|publisher=Coast Aire Publication|year=1991|page=299}}</ref> किनकि तिनीहरू "मुख्य राष्ट्रिय वायुसेवा" <ref>{{Cite web |title=flag airline definition |url=http://www.macmillandictionary.com/dictionary/british/flag-airline |url-status=live |archive-url=https://web.archive.org/web/20120707035611/http://www.macmillandictionary.com/dictionary/british/flag-airline |archive-date=7 July 2012 |access-date=9 December 2012 |publisher=[MacMillan Dictionary] }} {{Webarchive|url=https://web.archive.org/web/20120707035611/http://www.macmillandictionary.com/dictionary/british/flag-airline |date=7 July 2012 }}</ref> थिए र प्रायः विदेशमा उनीहरूको देशको उपस्थितिको संकेत थियो। <ref>{{Cite news|title=Airways Abroad; The Story of American World Air Routes|last=Henry Ladd Smith|publisher=Smithsonian History of Aviation Series|year=1991}}</ref> <ref>{{Cite news|title=Empires of the Sky; The Politics, Contests and Cartels of World Airlines|last=Sampson|first=Anthony|publisher=Hodder and Stoughton|year=1984}}</ref> == ध्वजा बाहक एयरलाइन्सहरूको सूची == तलको चार्टमा केही हालको वा भूतपूर्व राज्यको स्वामित्व वा राष्ट्रिय एयरलाइन्सहरूलाई प्रस्तुत गर्दछा। {| class="wikitable sortable" |- ! देश वा क्षेत्र ! वायुसेवा ! class="unsortable" | राष्ट्रिय स्वामित्वको विवरण ! class="unsortable" | पहिलेको स्वामित्व |- | {{AFG}} || एरिआना अफ्गान एयरलाइन्स<ref name="EU To Impose Ban On Afghan Planes" /> || State-owned<ref>{{cite news |last1=De Luce |first1=Dan |last2=Kube |first2=Courtney |title=Biden admin relies on Taliban-controlled airline to help Afghans flee Afghanistan |url=https://www.nbcnews.com/politics/national-security/us-indirectly-pays-airline-controlled-taliban-regime-fly-afghans-kabul-rcna32431 |access-date=17 March 2023 |work=[[NBC News]] |date=8 June 2022 |quote=the Biden administration indirectly purchases plane tickets in bulk from Ariana Afghan Airlines, the country’s state-owned airline}}</ref> || |- | {{ALB}} || एयर अल्बानिया<ref name="New national carrier for Albania launched" /> || || |- | {{DZA}} || एयर अल्जेरि<ref name="Air Algerie Eyeing African Tie-Ups" /> || State-owned<ref name="Air Algerie to spend $762 million upgrading its fleet" /> || |- | {{AGO}} || [[TAAG Angola Airlines]]<ref name="TAAG Angola Airways boosts capacity, justifying Angola's investment in airport infrastructure" />|| Majority<ref name="TAAG Angola Airlines’ new 777-300ER to fly on Portugal route" /> || |- | {{ARG}} || एरोलिनिया अर्जेन्टिनास<ref name="Argentina: Aerolineas Argentinas faces a tough turnaround with government's new liberal mindset" /> || State-owned<ref name="Argentina: Aerolineas Argentinas faces a tough turnaround with government's new liberal mindset" /> || |- | {{ARM}} || फ्लाई अर्ना<ref>{{cite web|url=https://www.routesonline.com/news/29/breaking-news/297381/-armenias-national-airline-fly-arna-reveals-initial-plans/|title=Armenia's National Airline Fly Arna Reveals Initial Plans|publisher=routesonline.com|access-date=2023-05-07}}</ref><ref>{{cite web|url=https://www.ch-aviation.com/portal/news/119462-armavia-founder-set-to-start-new-carrier|title=Armavia founder set to start new carrier|publisher=ch-aviation.com|access-date=2023-05-07}}</ref> || || |- | {{ABW}} || अरुबा एयरलाइन्स<ref>{{cite web|url=https://airwaysmag.com/tag/aruba-airlines/|title=The World's Shortest International Jet Flight? Aruba Airlines Launches 8-Minute Flight To Punto Fijo|publisher=Airways Magazine|date=19 May 2018|access-date=16 October 2022}}</ref> || None || |- | {{AUS}} || कन्टास<ref name="Brisbane named second Qantas 787-9 base" /> || None || State-owned until 1992.<ref name="Accelerating Change in the 1990s" /> |- | {{AUT}} || अस्ट्रियन एयरलाइन्स<ref name="Austrian Airlines completes Embraer E195 deliveries" />|| None – owned by [[Lufthansa]] || State-owned until 5 December 2008.<ref name="AUA-Verkauf besiegelt: Kranich soll Flügel verleihen" /> |- | {{AZE}} || {{nowrap|अजरबैजान एयरलाइन्स}}<ref name="Azerbaijan Airlines steps up Saudi links" /> || || |- | {{BHS}} || बहमास एयर<ref name="Bahamasair orders five ATR -600 aircraft" /> || State-owned || |- | {{BHR}} || [[गल्फ एयर]]<ref name="Gulf Air reveals new branding, prepares for first 787" />|| State-owned<ref name="Gulf Air" /> || |- | {{BGD}} || [[विमान बङ्गलादेश एअरलाइन्स]] <ref name="UK restores Bangladesh cargo link, with caveats" />|| Public limited company || State-owned until 23 July 2007. |- | {{BLR}} || [[Belavia]]<ref name="Belavia orders three Boeing 737-800s" /> || State-owned<ref name="Belarus aims to privatise Belavia in 2013, with Russian carriers the most likely suitors" /> || |- | {{BEL}} || ब्रसेल्स एयरलाइन्स<ref name="Brussels Airlines to buy seven Airbus A330ceos" /> || None – owned by [[Lufthansa]]<ref name="Pilot strike forces Brussels Airlines to cancel 75% of flights" /> || State-owned in its original incarnation ({{nowrap|[[SN Brussels Airlines]]}}) |- | {{BTN}} || [[ड्रुक एयर]]<ref name="Aircraft Briefs-20 April 2018" /> || None || |- | {{BOL}} || बोलिभियाना डे एभिएकिओन<ref name="ROUTES: Air Nostrum still keen on Latin American growth post-Sol" /> || State-owned<ref name="Boliviana de Aviacion set to expand as re-launch of Aerosur is unlikely due to government roadblocks" /> || |- | {{BWA}} || [[एयर बोत्स्वाना]]<ref name="Air Botswana receives first of two Embraer E170s" /> || State-owned<ref name="Air Botswana receives first of two Embraer E170s" /> || |- | {{BRN}} ||रोयल ब्रुनाई एयरलाइन्स<ref name="Royal Brunei Airlines takes another step forward as it becomes first 787 operator in Southeast Asia" /> || State-owned<ref name="Royal Brunei Airlines takes another step forward as it becomes first 787 operator in Southeast Asia" /> || |- | {{BGR}} || बुल्गेरिया एयर<ref name="Bulgaria Air strengthens its European network with new E-Jets" /> || Minority State-owned (0.01%)<ref name="econ.bg" /> || |- | {{BFA}} || एयर बुर्किना ||सरकारी-स्वामित्वको<ref>{{cite web|title=Air Burkina prend son envol avec le gouvernement burkinabè|url=https://www.voaafrique.com/a/air-burkina-prend-son-envol-avec-le-gouvernement-burkinabe/3874682.html|access-date=19 January 2021|website=VOA|language=fr}}</ref> | |- | {{KHM}} || कम्बोडिया एङ्कोर एयर<ref name="Cambodia poised for more double-digit growth as Cambodia Angkor Air expands and Qatar Airways enters" /> || Majority (51%)<ref name="Cambodia launches national carrier with Vietnam's help" /> || |- | {{CMR}} || [[Camair-Co]]<ref name="New Cameroon national carrier Camair-Co fails to reach first year targets, but continues to grow" /> ||State-owned<ref>{{cite web|last=|first=|date=|title=À propos de la companie (french)|url=https://www.camair-co.cm/page/CM/en/a-propos-de-la-compagnie|access-date=|website=Camair-co}}</ref> | |- | {{CAN}} || एयर क्यानडा<ref name="Aircraft News-31 July 2015" /> || Minority state-owned by the [[Government of Canada]] (Estimated 6.4%)<ref>{{cite web|title=Canadian Taxpayers Now Own Part of Air Canada|url=https://ca.travelpulse.com/news/airlines/canadian-taxpayers-now-own-part-of-air-canada.html|access-date=12 October 2021|website=TravelPulse}}</ref>|| State-owned until privatization in 1989.<ref name="Air Canada Timeline" /> |- | {{CPV}} || [[TACV]]<ref name="Loftleidir Icelandic to manage TACV Cabo Verde" /> || || |- | {{CYM}} || [[Cayman Airways]] || State-owned <ref name="Cayman Airways – Our History" /> || |- | {{CHL}} || [[LATAM Chile]]<ref name="BOC Aviation to lease one new A320-200 to LAN" /><ref name="ATAM Kicks Off Regular Flights, Announces Johannesburg" /> || None || State-owned until September 1989.<ref name="lancargo history" /> |- | {{CHN}} || [[एयर चाइना]]<ref name="Air China to take six more 777-300ERs" /> || Majority (51.7%): 40.98% through [[China National Aviation Holding|CNAHC]] and 10.72% through [[China National Aviation Company Limited|CNACG]]<ref name="CCA-report-2017" />{{rp|10}} || State-owned until 2004.<ref name="Air China Transfers Ownership from State-owned to Shareholding" /> |- | {{COL}} || [[Avianca]]<ref name="Aircraft Briefs-4 Jan. 2017" /> || None || |- | {{CRI}} || [[Avianca Costa Rica]]<ref>{{cite web|url=https://centreforaviation.com/data/profiles/airlines/avianca-costa-rica-lr|title=Avianca Costa Rica Airline Profile - CAPA - Centre for Aviation}}</ref> || || |- | {{HRV}} || [[Croatia Airlines]]<ref name="Croatia again seeks airline partner" /> || Majority&nbsp;(98%)<ref name="Croatia Airlines: could its network attract a bidder?" /> || |- | {{CUB}} || [[Cubana de Aviación]]<ref name="First direct Brazil flight to take off in July" /> || State-owned<ref>{{cite web |last1=Urribares |first1=Ruben |title=The Cuban Civil Aviation after the Revolution of 1959 |url=http://www.urrib2000.narod.ru/Civ4-e.html |website=Cuban Aviation |access-date=23 March 2022}}</ref> || |- | {{CYP}} || [[Cyprus Airways]]<ref>{{cite web|url=https://www.traveldailynews.com/post/cyprus-airways-opens-partner-office-in-the-uk|title=Cyprus Airways opens partner office in the UK|publisher=Travel Daily News|date=29 September 2021|access-date=28 February 2022}}</ref>|| None - 40% owned by [[Malta]]-based SJC Group<ref>{{cite web|title=Cyprus Airways confirms acquisition by SJC Group|url=https://centreforaviation.com/news/cyprus-airways-confirms-acquisition-by-sjc-group-1077323|publisher=Centre for Aviation|date=1 July 2021|access-date=28 February 2022}}</ref> || |- | {{CZE}} || [[Czech Airlines]]<ref name="Leisure carrier Travel Service is CSA Czech Airlines new owner" /> || None<ref name="Leisure carrier Travel Service is CSA Czech Airlines new owner" /> || |- | {{no wrap|{{flag|DR Congo}}}} || [[Congo Airways]]<ref name="Congo Airways to make international debut in mid-4Q" /> || State-owned<ref name="Congo Airways to make international debut in mid-4Q" /> || |- | {{DNK}} || rowspan="3" | {{nowrap|[[Scandinavian Airlines]]}}<ref name="SAS aims to capture a larger share of the thriving Scandinavian leisure market" /> || rowspan="3" | Joint venture{{#tag:ref|[[Scandinavian Airlines|SAS]] is partly owned by the governments of [[Denmark]] and [[Sweden]], and was partly owned by the government of [[Norway]] until June 2018. SAS is the flag carrier for all three nations.<ref name="SAS aims to capture a larger share of the thriving Scandinavian leisure market" /><ref name="Sweden, Norway sell 7% of SAS Scandinavian Airlines" /><ref name="NorGov sell SAS 2018" />|group="nb"|name="SAS"}}|| rowspan="3" |&nbsp; |- | {{NOR}} |- | {{SWE}} |- | {{DJI}} || [[Air Djibouti]]<ref name="Africa’s Air Djibouti continues re-fleeting" /> || Joint venture || |- | {{EGY}} || [[Egyptair]]<ref name="Egyptair plans further restructuring as losses mount. But outlook may brighten as Egypt stabilises" /> || State-owned<ref name="Egyptair contracts Sabre to help implement transformation plan" />|| |- | {{GNQ}} || [[CEIBA Intercontinental]]<ref>{{cite web|url=https://www.prnewswire.com/news-releases/equatorial-guinea-airline-inaugurates-service-to-europe-173302031.html|title=Equatorial Guinea Airline Inaugurates Service To Europe|first=Republic of Equatorial|last=Guinea|website=www.prnewswire.com}}</ref> || || |- | {{ERI}} || [[Eritrean Airlines]] || State-owned || |- | {{EST}} || [[Nordica (airline)|Nordica]]<ref name="Nordica 1Q passenger traffic up 17%, forecasts strong growth" /> || State-owned<ref name="Nordica launches services from Tallinn to Vienna, Berlin" /> || |- | {{ETH}} || [[Ethiopian Airlines]]<ref name="Ethiopian Airlines finalizes deal for new Chad JV carrier" /> || State-owned<ref name="Ethiopian Airlines Fact Sheet" /> || |- | {{FRO}} || [[Atlantic Airways]]<ref name="Island carrier Atlantic Airways seeks new revenue stream" /> || || |- | {{FJI}} || [[Fiji Airways]]<ref name="Fiji Airways introduces additional Hong Kong route" />|| Majority (51%)<ref name="Fiji Airways' new MD Stefan Pichler sets his sights on the next five years for the rebranded airline" /> || |- | {{FIN}} || [[Finnair]]<ref name="Finnair brings in capacity support" /> || Majority (55.8%)<ref name="Finnair Group" /> || |- | {{FRA}} || [[Air France]]<ref name="Air France KLM Group CEO resigns; Spinetta and Van Wijk return" />|| Minority (18% share)<ref name="French Government Seeks Shareholder Power at Air France-KLM" /> || |- | {{PYF}} || [[Air Tahiti Nui]]<ref name="Air Tahiti Nui plans metal neutral alliance with Air France and partners as losses continue to mount" /> || Majority<ref name="Air Tahiti Nui – Corporal Profile" /> || |- | {{GEO}} || [[Georgian Airways]] || None || |- | {{DEU}} || [[Lufthansa]]<ref name="Lufthansa cuts back A380 order" /> || Minority (20.05%) in the [[Lufthansa Group|parent company]] since 2020 due to near-insolvency as a result of the COVID-19 pandemic <ref>{{cite web |url=https://investor-relations.lufthansagroup.com/en/share-bonds/shareholder-structure.html |title=Shareholder structure of Lufthansa Group |access-date= 19 December 2020}}</ref><ref>{{cite news |title=Lufthansa-Aktionäre stimmen Staatseinstieg zu |language=de |url=https://www.faz.net/aktuell/wirtschaft/unternehmen/lufthansa-aktionaere-stimmen-staatseinstieg-zu-16832849.html |publisher= Frankfurter Allgemeine Zeitung (FAZ) |date=25 June 2020 | access-date= 19 December 2020}}</ref> || State-owned until 1994;<ref name="Lufthansa privatization" /> remaining government shares were sold in 1997.<ref name="German Cabinet Backs Selling Lufthansa" /> |- | {{GRC}} || [[Aegean Airlines]]<ref name="Aegean 1Q losses widen as it invests in capacity" /> || || |- | {{GRL}} || [[Air Greenland]]<ref name="Airline News-1 May 2015" /> || || |- | {{flag|Bailiwick of Guernsey|name=Guernsey}} || [[Aurigny]]<ref name="Hahn Air’s new partner Aurigny now available in 190 markets" /> || State-owned<ref name="Guernsey States' ownership of Aurigny 'essential'" /> || |- | {{GUY}} || rowspan=3|[[Caribbean Airlines]]<ref name="Republic Bank, Caribbean Airlines involved in Guyana’s jubilee celebration" /><ref name="Macquarie AirFinance Ltd press release" /><ref name="Status quo for Caribbean Airlines – chaos surrounds the would-be flag carrier of the region" /> || None{{citation needed|date=September 2021}} || |- | {{JAM}} || Minority (16%){{citation needed|date=September 2021}} || |- | {{TTO}} || Majority (84%)<ref name="Caribbean Airlines: News/PR" /> || |- | {{HKG}} || [[Cathay Pacific]]<ref name="Shrinking Jumbos: Top Ten 747-400 fleets still in service" /> || Minority (6.08% by [[Government of Hong Kong|Hong Kong Government]]) + 28.17% through [[Air China Limited]]<ref>{{cite web|title=【國泰資本重組】香港政府斥273億元救國泰 若實行認股權變第四大股東 - 香港經濟日報 - 即時新聞頻道 - 金融經濟|url=https://inews.hket.com/article/2665394|access-date=9 June 2020|website=inews.hket.com}}</ref>|| |- | {{ISL}} || [[Icelandair]]<ref name="Icelandair faces indefinite strike action" /> || None - owned by [[Icelandair Group]]<ref>{{cite web |title=20 largest shareholders as of 08.09.2021 |url=https://www.icelandairgroup.is/investors/shares/shareholders/ |website=Icelandair Group |access-date=9 September 2021}}</ref>|| |- | {{IND}} || [[एअर इन्डिया]]<ref name="Plane paint: Top 10 Indian liveries" /> || None - owned by [[Tata Group]]<ref>{{cite news|title= Its handover complete, Air India returns to Tata home after 69 yrs|first= Pranav|last= Mukul|date= 28 January 2022|location= New Delhi|url= https://indianexpress.com/article/india/tata-group-takes-over-air-india-7744206/|archive-url= https://web.archive.org/web/20220128203226/https://indianexpress.com/article/india/tata-group-takes-over-air-india-7744206/|archive-date= 28 January 2022|access-date= 28 January 2022|url-status= live}}</ref>||State-owned until November 2021<ref name="Plane paint: Top 10 Indian liveries" /><ref>{{Cite news|date=8 October 2021|title=Air India: Struggling national carrier sold to Tata Sons|language=en-GB|work=BBC News|url=https://www.bbc.com/news/world-asia-india-58778274|access-date=11 October 2021}}</ref><ref>{{cite web|date=Oct 8, 2021|title=Sentiments and business: What Air India acquisition means for Tatas - Times of India|url=https://timesofindia.indiatimes.com/business/india-business/sentiments-and-business-what-air-india-acquisition-means-for-tata/articleshow/86871669.cms|access-date=11 October 2021|website=The Times of India|language=en}}</ref> |- | {{IDN}} || [[Garuda Indonesia]]<ref name="Garuda Indonesia may be forced to change Amsterdam service" />|| Majority (60.536%)<ref>{{cite web|url=http://www.idx.co.id/|title=Indonesia Stock Exchange|website=Indonesia Stock Exchange|language=en|access-date=21 December 2019}}</ref>||State-owned until February 2011.<ref>{{cite web|url=https://www.beritasatu.com/ekonomi/10805/mengapa-ipo-garuda-buntung|title=Mengapa IPO Garuda buntung?|last=BeritaSatu.com|website=beritasatu.com|date=21 February 2011 |language=id|access-date=21 December 2019}}</ref> |- | {{IRN}} || [[Iran Air]]<ref name="Iran Air takes first Airbus widebody from major order" /> || State-owned<ref name="iran-air-plans-share-sale-to-finance-growth-fleet-upgrade" /> || |- | {{IRQ}} || [[Iraqi Airways]]<ref name="Kuwait Airways and Iraqi Airways face brighter future following settlement of long-running dispute" /> || || |- | {{IRL}} || [[Aer Lingus]]<ref name="Aer Lingus to bring back short-haul premium service with A321neo LR" /><ref name="=AER LINGUS GRP Share Price Chart" /> || None – owned by [[International Airlines Group]] || State-owned until September 2006.<ref name="Irish Independent: Key dates in Aer Lingus history" /> |- | {{ISR}} || [[El Al]]<ref name="Aircraft & Engines-13 March 2015" /> || Minority (~1.1%)<ref name="El Al IR 2013" /> || State-owned until June 2004. |- | {{ITA}} || [[Ita Airways|ITA Airways]]<ref>https://www.itaspa.com/content/itaspa/itaspa-pl/it/homepage.html {{Webarchive|url=https://web.archive.org/web/20240927011329/https://www.ita-airways.com/en_en |date=2024-09-27 }} {{Bare URL inline|date=March 2022}}</ref> ||State-owned, succeeded [[Alitalia]] starting from 15 October 2021<ref>{{cite web|url= https://www.corriere.it/economia/aziende/21_ottobre_13/alitalia-ultimo-volo-ora-tocca-ita-tutti-dossier-aperti-marchio-millemiglia-bdf2cf58-2c5d-11ec-98f9-fbd4bdd13a87.shtml|language=it-IT|title=Alitalia, ultimo volo: Ora tocca a Ita. Tutti i dossier aperti dal marchio a MilleMiglia|date=13 October 2021}}</ref><ref>{{cite web|url= https://www.ansa.it/english/news/business/2021/10/14/old-alitalia-set-for-last-flight-after-75-years_62620b08-7c82-456b-a5b8-305ae2658600.html|language=en-EN|title='Old' Alitalia set for last flight after 75 years - English|date=14 October 2021}}</ref><ref>{{cite news|url=https://www.cnn.com/travel/article/ita-airline-explainer/index.html|title=What to know about Europe's newest airline|author=Julia Buckley|date=8 October 2021|website=CNN Travel}}</ref> || |- | {{CIV}} || [[Air Côte d'Ivoire]]<ref name="Bombardier to sell eight Q400 NextGen aircraft to Palma Holding" /> || Minority (49%) || |- | {{JPN}} || [[Japan Airlines]]<ref name="JAL reports 17.5% net profit drop on deferred taxes" /> || None || State-owned until 1987.<ref name=histfu>{{cite web|title=Japan Airlines Company, Ltd.|url=http://www.fundinguniverse.com/company-histories/Japan-Airlines-Company-Ltd-Company-History.html|publisher=fundinguniverse.com|access-date=6 September 2009}}</ref><ref name=hist80s>{{cite web|title=History of JAL 1981–1990|url=http://www.jal.com/en/history/history/age_81-90.html|publisher=Japan Airlines|access-date=6 September 2009}}</ref> |- | {{JOR}} || [[Royal Jordanian]]<ref name="Middle Eastern carriers drop routes" /> || || |- | {{KAZ}} || [[Air Astana]]<ref name="Air Astana reports strong 1H traffic on 8% capacity increase" /> || Majority&nbsp;(51%)<ref name="Air Astana eyes Paris and Prague services after EU lifts safety ban" /> || |- | {{KEN}} || [[Kenya Airways]]<ref name="Kenya Airways adds flights to Livingstone, Zambia" /> || Minority&nbsp;(29.8%)<ref name="Government now largest shareholder of Kenya Airways" /> || |- | {{KIR}} || [[Air Kiribati]]<ref name="Air Kiribati to boost fleet, connectivity with Embraer E-Jets order" /> || || |- | {{KWT}} || [[Kuwait Airways]]<ref name="Kuwait Airways prepares for Amadeus switchover" /> || State-owned<ref name="Kuwait Airways names new CEO" />|| |- | {{LAO}} || [[Lao Airlines]]<ref name="Lao Airlines plans route expansion" /> || State-owned<ref name="Laos aviation market poised for more rapid growth after doubling in size in only 15 months" /> || |- | {{LVA}} || [[Air Baltic|airBaltic]]<ref name="Dubai Air Show: airBaltic takes lead on Bombardier CS300" /> || Majority (80.05%)<ref name="New investor completes airBaltic buy-in" /> || |- | {{LBN}} || [[Middle East Airlines]]<ref name="MEA advances Airbus deliveries schedule" /> || Majority (99%)<ref name="MEA advances Airbus deliveries schedule" /> || |- | rowspan="2" | {{LBY}}||[[Afriqiyah Airways]]<ref name="PICTURE: Afriqiyah Airways unveils new livery" /> || State-owned<ref name="Libya’s economy recovers as airlines restore networks post-revolution" /> || |- | [[Libyan Airlines]]<ref name="Libyan Airlines Takes Delivery of its First Airbus A330" /> || State-owned<ref name="Libyan Airlines Takes Delivery of its First Airbus A330" /> || |- | {{LUX}} || [[Luxair]]<ref name="Luxair to increase frequencies and destinations" />|| Majority (73.86%)<ref name="About Luxair Group – Shareholders" /> || |- | {{MAC}} || [[Air Macau]]<ref name="Air Macau takes encouraging steps to support the Macau market as resort tourism balloons" />|| Minority (5%) || |- | {{MDG}} || [[Air Madagascar]]<ref name="More ATRs for Madagascar" /> || Majority || |- | {{MWI}} || [[Malawian Airlines|Malawi Airlines]]<ref name="NyasaTimes" /> || Majority (51%)<ref name="NyasaTimes" /> || |- | {{MYS}} || [[मलेसिया एअरलाइन्स]]<ref name="Malaysia Airlines pursues rapid expansion but yields and profits are under pressure" /> ||State-owned through [[Khazanah Nasional]]<ref name="Selected Portfolio of Companies" /> || |- | {{MDV}} || [[Maldivian (airline)|Maldivian]] || || |- | {{MLT}} || [[Air Malta]]<ref name="Air Malta expands route network" />|| Majority<ref name="Book your flights to Malta with Air Malta" /> || |- | {{MRT}} || [[Mauritania Airlines]]<ref name="Mauritania Airlines finalizes Boeing 737-800 order" /> || || |- | {{MUS}} || [[Air Mauritius]]<ref name="Mauritius bids for key Asia-Africa transit hub status" /> || &nbsp; || |- | {{MEX}} || [[Aeroméxico]]<ref name="Aeromexico set to put first MAX into service" /> || None || State-owned until 2007. |- | {{MDA}} || [[Air Moldova]]<ref name="Government puts Air Moldova up for sale" /> || || |- | {{MNG}} || [[MIAT Mongolian Airlines]]<ref name="MIAT Mongolian Airlines to lease two Boeing 737 MAXs" /> || State-owned<ref name="MIAT Mongolian Airlines" /> || |- |{{MNE}} |[[Air Montenegro]]<ref>{{cite web|date=1 June 2021|title=Air Montenegro prvi let|url=https://airmontenegro.com/footer/o-nama/vijesti/vijest/air-montenegro-prvi-let|url-status=live|access-date=29 November 2021|website=Air Montenegro}}</ref> |State-owned<ref>{{cite web|date=2 March 2021|title=Predstavljeno rukovodstvo, ciljevi i planovi "ToMontenegro"|url=http://www.gov.me/clanak/predstavljeno-rukovodstvo-ciljevi-i-razvojni-planovi-nove-nacionalne-avio-kompanije-tomontenegro-5|url-status=live|access-date=29 November 2021|website=Vlada Crne Gore|publisher=Government of Montenegro|language=sr-Latn-ME}}</ref> | |- | {{MAR}} || [[Royal Air Maroc]]<ref name="Royal Air Maroc, pilot union reach agreement to end dispute" /> ||State-owned<ref name="Royal Air Maroc sees fleet, hub growth ahead of oneworld membership" /> || |- | {{MOZ}} || {{nowrap|[[LAM Mozambique Airlines]]}}<ref name="Mozambique is latest state to face EU blacklist ban" /> || State-owned || |- | {{flag|Myanmar}} || [[Myanmar National Airlines]]<ref name="Myanmar Airlines continues fleet upgrade" /> || State-owned<ref name="Myanmar Airways inks deal for up to 12 ATR 72-600s" /> || |- | {{NRU}} || [[Nauru Airlines]]<ref name="Nauru Airlines begins new chapter with new brand & rapid growth despite world’s smallest home market" />|| State-owned<ref name="Nauru Airlines begins new chapter with new brand & rapid growth despite world’s smallest home market" /> || |- | {{NPL}} || [[नेपाल वायुसेवा निगम|नेपाल एयरलाइन्स]]<ref name="Nepal Airlines’ first A330 will expand international network" /> || State-owned || |- | {{NLD}} || [[KLM]]<ref name="KLM expands long-haul network" />|| Minority (14%)<ref name="Nederlandse staat vergroot belang in Air France-KLM" /> || |- | {{flag|New Caledonia}} || [[Aircalin]] || Majority (99%)<ref>{{cite web|url=https://www.ch-aviation.com/portal/news/80945-new-caledonias-aircalin-to-end-a330-200-ops-in-late-3q19|title=New Caledonia's Aircalin to end A330-200 ops in late 3Q19|website=ch-aviation}}</ref> || |- | {{NZL}} || [[Air New Zealand]]<ref name="Air New Zealand boosts network to replace Virgin Australia alliance" />||Majority&nbsp;(53%)<ref name="New Zealand government cuts stake in Air New Zealand to 53%" />|| State-owned until 1989, partially re-nationalized in 2001.<ref>{{Cite news|url=http://www.nzherald.co.nz/|title=Government bailout of Air NZ complete|date=18 January 2002|work=NZ Herald|access-date=12 March 2018|language=en-NZ|issn=1170-0777}}</ref><ref>{{cite web|title=History - About Air New Zealand|url=https://www.airnewzealand.com.sg/history|website=www.airnewzealand.com.sg|publisher=Air New Zealand Singapore|access-date=10 December 2017|language=en-SG}} {{Webarchive|url=https://web.archive.org/web/20171210072034/https://www.airnewzealand.com.sg/history |date=10 December 2017 }}</ref><ref name="CompanyHistory">{{cite web |url=http://www.airnz.co.nz/resources/company_history_feb_06.pdf |title=Air New Zealand History |access-date=28 February 2007 |publisher=Air New Zealand |url-status=dead |archive-url=https://web.archive.org/web/20070621151238/http://www.airnz.co.nz/resources/company_history_feb_06.pdf |archive-date=21 June 2007 }} {{Webarchive|url=https://web.archive.org/web/20070621151238/http://www.airnz.co.nz/resources/company_history_feb_06.pdf |date=21 June 2007 }}</ref> |- | {{PRK}} || [[Air Koryo]]<ref name="SOLDIERING ON: 10 veteran airliner types still in service" /> || State-owned<ref name="Air Koryo" /> || |- | {{OMN}} || [[Oman Air]]<ref name="Omani flag carrier names new CCO" /> || Majority<ref name="Oman Air reports record passengers, but also record losses" /> || |- | {{PAK}} || {{Nowrap|[[पाकिस्तान अन्तर्राष्ट्रिय एयरलायन्स|Pakistan International Airlines]]<ref name="CEO: Pakistan International Airlines wet-leases three SriLankan A330s" />}}|| State-owned<ref name="Pakistan International Airlines privatization plans delayed to 2016" /> || |- | {{PAN}} || [[Copa Airlines]]<ref name="United, Avianca and Copa consider joint business agreement" /> || None || |- | {{PNG}} || [[Air Niugini]]<ref name="Aircraft, Engine & Leasing Briefs-25 April 2018" /> || || |- | {{PAR}} || [[LATAM Paraguay]]<ref>{{cite web|url=https://centreforaviation.com/data/profiles/airlines/latam-airlines-paraguay-pz|title=LATAM Airlines Paraguay - CAPA - Centre for Aviation}}</ref>|| || |- | {{PER}} || [[LATAM Perú]]<ref>{{cite web|url=https://centreforaviation.com/data/profiles/airlines/latam-airlines-peru-lp|title=LATAM Airlines Peru Airline Profile - CAPA - Centre for Aviation}}</ref>|| || |- | {{PHL}}||[[Philippine Airlines]]<ref name="Philippine Airlines to open new LAX service" /> || || |- | {{POL}} || [[LOT Polish Airlines]]<ref name="First seats from Boeing partner LIFT enter service" /> || State-owned<ref name="LOT cancels flights, fires workers as week-long crew strike continues" /> || |- | {{PRT}} || [[TAP Air Portugal]]<ref name="TAP reports 11.3% traffic growth on African routes in 2018" /> || Majority (72%) <ref>{{cite web|last=Siza|first=Ana Brito, Ana Sá Lopes, São José Almeida, Rita|title=Estado fica com 72,5% da TAP e assume controlo|url=https://www.publico.pt/2020/07/02/economia/noticia/estado-preparase-tomar-controlo-tap-1922735|access-date=11 July 2020|website=PÚBLICO|language=pt}}</ref> || |- | {{QAT}} || [[कतार एयरवेज]]<ref name="Qatar Airways to increase service to Iran" /> || State-owned || |- | {{REU}} || [[Air Austral]]<ref name="Vanilla Islands carriers Air Seychelles and Air Austral make capacity cuts" /> || || |- | {{ROU}} || [[TAROM]]<ref name="Romania’s Tarom issues RFP to dry lease 13 regional jets" /> || Majority (95%)<ref name="Mission and people" /> || |- | {{RUS}} || [[Aeroflot]]<ref name="Aeroflot commits to another 20 Superjets" /> || Majority (51%)<ref name="Aeroflot profits up on regional airlines turnaround" /> || |- | {{RWA}} || [[RwandAir]]<ref name="Ethiopian Airlines, RwandAir eye strategic partnership" /> ||State-owned<ref name="Ethiopian Airlines, RwandAir eye strategic partnership" />|| |- | {{nowrap|{{VCT}}}} || [[SVG Air]]{{citation needed|date=February 2021}} || || |- | {{WSM}} || [[Samoa Airways]]<ref name="Air of confidence about Samoa's new flag carrier" /> || State-owned<ref name="Samoan government says state airline must be self-sufficient" /> || |- | {{STP}} || [[STP Airways]]{{citation needed|date=February 2021}} || None || |- | {{SAU}} || [[Saudia]]<ref name="Air Partner remarkets 15 Saudia Boeing 777-200ERs" /> || Majority || |- | {{SEN}} || [[Air Senegal]]<ref name="Air Senegal signs for two ATR 72-600s" /> || || |- | {{SRB}} || [[Air Serbia]]<ref name="Air Serbia’s 2015 net profit up 44%" />|| Majority&nbsp;(51%)<ref name="Air Serbia records first full-year profit in 2014" /> || |- | {{SYC}} || [[Air Seychelles]]<ref name="Air Seychelles looks to ride Chinese boom & grow in tandem with part-owner Etihad – Australia next?" /> || State-owned (100%)<ref>{{cite web|date=1 May 2021|title=Etihad divests full stake in Air Seychelles|url=https://www.thenationalnews.com/business/aviation/etihad-divests-full-stake-in-air-seychelles-1.1214447|access-date=1 June 2021|website=The National|language=en}}</ref>|| |- | {{SLB}} || [[Solomon Airlines]]<ref name="Solomon Airlines to resume services following grounding" /> || State-owned (100%)<ref name="Solomon Airlines" /> || |- | {{SGP}} || [[Singapore Airlines]]<ref name="Singapore Airlines in $20 million government-led tourism push" /> || Majority (54.5% through [[Temasek Holdings]]<ref name="Reuters profit" />) || |- | {{ZAF}} || [[South African Airways]]<ref name="South African Airways to receive financial support" /> || State-owned<ref name="South African Airways clarifies recovery plan funding" /> || |- | {{KOR}} || [[Korean Air]]<ref name="Cho: Korean Air deciding on new widebody orders" /> || None<ref name="Member Airline Korean Air" /> – owned by [[Hanjin]]<ref name="HanjinOwnership">{{cite web|title=Korean Air info on Hanjin corporate website|publisher=[[Hanjin|Hanjin KAL Corporation]]|url=https://www.hanjinkal.co.kr/en/contentsid/647/index.do|access-date=28 June 2022}} {{Webarchive|url=https://web.archive.org/web/20240927152645/https://www.hanjinkal.co.kr/en/contentsid/647/index.do |date=27 September 2024 }}</ref>||State-owned until 1969.<ref>{{cite news|title= Korean Air turns 50 with eye on growth|first= Min-ji|last= Jin|publisher=Korea JoongAng Daily|date= 5 March 2019|url= http://koreajoongangdaily.joins.com/news/article/article.aspx?aid=3060133}}</ref><ref>https://www.koreanair.com/mobile/global/ko-backup/about/who-we-are2/history-awards.html {{Webarchive|url=https://web.archive.org/web/20200731170225/https://www.koreanair.com/mobile/global/ko-backup/about/who-we-are2/history-awards.html |date=2020-07-31 }} {{Bare URL inline|date=March 2022}}</ref><ref>https://kr.img.news.koreanair.com/wp-content/uploads/2019/11/%EC%98%81%EB%AC%B8-%ED%99%94%EB%B3%B4-1.pdf {{Bare URL PDF|date=March 2022}}</ref> |- | {{ESP}} || [[Iberia (airline)|Iberia]]<ref name="Iberia increases frequencies to six Latin American destinations" />|| None – owned by [[International Airlines Group]]|| |- | {{LKA}} || [[SriLankan Airlines]]<ref name="New SriLankan board to push through restructuring" /> || State-owned<ref name="SriLankan Airlines buys back 43.6 pc stake from Emirates" /> || |- | {{SDN}} || [[Sudan Airways]] || State-owned<ref name="Sudan Dreams Big With New Airports" /> || |- | {{SUR}} || [[Surinam Airways]]<ref name="Putting Surinam on the map" /> || State-owned<ref name="Suriname state oil company considers share offering" /> || |- | {{CHE}} || [[Swiss International Air Lines]]<ref name="Lufthansa Group orders 15 A320neos for SWISS subsidiary" /> || None – owned by [[Lufthansa]]<ref name="Lufthansa Group Corporate Structure" /> || |- | {{SYR}} || [[Syrian Air]]<ref name="Syrian Arab Airlines" /> || State-owned || |- | {{TWN}} || [[China Airlines]]<ref name="Taiwan’s China Airlines takes delivery of first Boeing 777-300ER" /> || Majority<ref name="China Airlines Majority Ownership" /> || State-owned until 1991. 51.28% held by non-profit Civic Aviation Development Foundation.<ref name="China Airlines ABOUT" /> |- | {{TZA}} || [[Air Tanzania]] || State-owned || |- | {{THA}} || [[थाइ एयरवेज]]<ref name="International airlines increase capacity, frequencies to Russia" /> || Minority (47.86%)<ref name="Thai Airways submits bankruptcy request court says" /> || |- | {{TUN}} || [[Tunisair]]<ref name="Tunisair’s sluggish attitude towards change makes it ill-prepared for Open Skies" /> || Majority<ref name="Tunisair’s sluggish attitude towards change makes it ill-prepared for Open Skies" /> || |- | {{TUR}} || [[टर्किस एअरलाइन्स]]<ref name="Turkish Airlines swings to net profit in 1Q" /> || Minority (49%) || |- | {{TKM}} || [[Turkmenistan Airlines]]<ref name="Turkmenistan Airlines receives first Boeing 777-200LR" />|| State-owned || |- | {{UGA}} || [[Uganda Airlines]]<ref name="Revived Uganda flag carrier orders CRJ900s, A330neos" />|| || |- | {{UKR}} || {{nowrap|[[Ukraine International Airlines]]<ref name="Ukraine International to double international network as Aerosvit restructures" />}} || &nbsp; || |- | rowspan="2" | {{ARE}} || [[इतिहाद वायुसेवा|इतिहाद एयरवेज]] <ref name="Etihad, Avianca Brasil ink new codeshare" /> || State-owned by the [[Abu Dhabi|Government of Abu Dhabi]]<ref name="Etihad Holds Roadshows To Finance Aircraft" /><ref name="Etihad Slightly Ahead in Plan to Return to Profitability" /> || |- | [[Emirates (airline)|Emirates]]<ref name="Etihad Suspends Flights To Damascus" /> || State-owned by the [[Government of Dubai]] through the [[Investment Corporation of Dubai]].<ref name="Emirates and Dnata now under ICD" /> || |- | {{GBR}} || [[British Airways]]<ref name="IAG reports strong 1Q as passenger revenues improve" /> || None – owned by [[International Airlines Group]]|| State-owned until 1987.<ref name="Profile: British Airways" /> <!-- The U.S. does not have a flag carrier. Pan American was only claimed to be a flag carrier because of an ad campaign slogan. The "U.S. flag" requirement of Fly America is not the same as a flag carrier. American, United, and Delta aren't "de facto" flag carriers. Southwest Airlines, although it is the largest airline of America, is not the flag carrier either. Thank you for not changing this. --> |- | {{UZB}} || [[Uzbekistan Airways]]<ref name="Uzbekistan Airways takes first Boeing 787" /> || Majority || |- | {{VEN}} || [[Conviasa]]<ref>{{cite web|url=http://www.conviasa.aero/es/nosotros/historia|title=Conviasa - El Placer de Volar|website=www.conviasa.aero}} {{Webarchive|url=https://web.archive.org/web/20200731215910/http://www.conviasa.aero/es/nosotros/historia |date=2020-07-31 }}</ref>|| || |- | {{VNM}} || [[Vietnam Airlines]]<ref name="Vietnam Airlines continues to dominate international market" />|| Majority&nbsp;(86.2%)<ref name="Vietnam Airlines continues to dominate international market" />|| |- | {{VUT}} || [[Air Vanuatu]]<ref name="All About Air Vanuatu" /> || || |- | {{YEM}} || [[Yemenia]]<ref name="Yemenia suspends services" /> || Majority || |- | {{ZWE}} || [[Air Zimbabwe]]<ref name="flyafrica.com and fastjet give Zimbabwe its first taste of LCCs with local start-up" /> || State-owned<ref name="flyafrica.com and fastjet give Zimbabwe its first taste of LCCs with local start-up" /> || |} ==सन्दर्भ सामग्रीहरू== {{reflist}} [[श्रेणी:विमानसेवाहरू]] [[श्रेणी:All articles with dead external links]] 7d39z9uadzrh2lt8391vx4hs5ucz5ex ढाँचा:नेपालको संविधान २०७२ 10 134947 1361155 1356348 2026-06-11T12:22:38Z Bishaldev100 28807 1361155 wikitext text/x-wiki {{Sidebar with collapsible lists | name = नेपालको संविधान २०७२ | pretitle = Part of [[:Category:नेपालको संविधान|a series]] on the | title = [[नेपालको संविधान २०७२]] | image = [[File:Emblem of Nepal.svg|100px]] | listtitlestyle = padding-bottom:0; | contentclass = plainlist | contentstyle = padding-top:0; | expanded = {{{expanded|{{{selected|{{{1|}}}}}}}}} | content1 = '''[[नेपालको_संविधान_२०७२#प्रस्तावना|प्रस्तावना]]''' | list2title = [[नेपालको_संविधान_२०७२#संविधानका_भागहरू|भागहरू]] | list2 = [[नेपालको_संविधान_२०७२#भाग–१_प्रारम्भिक|१]] ∙ [[नेपालको_संविधान_२०७२#भाग–२_नागरिकता|२]] ∙ [[नेपालमा मौलिक हक र कर्तव्य|३]] ∙ [[नेपालको_संविधान_२०७२#भाग–४_राज्यका_निर्देशक_सिद्धान्त,_नीति_तथा_दायित्व|४]] ∙ [[नेपालको_संविधान_२०७२#भाग–५_राज्यको_संरचना_र_राज्य_शक्तिको_बाँडफाँड|५]] ∙ [[नेपालको_संविधान_२०७२#भाग–६_राष्ट्रपति_र_उपराष्ट्रपति|६]] ∙ [[नेपालको_संविधान_२०७२#भाग–७_सङ्घीय_कार्यपालिका|७]] <br> [[नेपालको_संविधान_२०७२#भाग_-_८_सङ्घीय_व्यवस्थापिका|८]] ∙ [[नेपालको_संविधान_२०७२#भाग–९_सङ्घीय_व्यवस्थापन_कार्यविधि|९]] ∙ [[नेपालको_संविधान_२०७२#भाग–१०_सङ्घीय_आर्थिक_कार्यप्रणालि|१०]] ∙ [[नेपालको_संविधान_२०७२#भाग–११_न्यायपालिका|११]] ∙ [[नेपालको_संविधान_२०७२#भाग–१२_महान्यायाधिवक्ता|१२]] ∙ [[नेपालको_संविधान_२०७२#भाग–१३_प्रादेशिक_कार्यपालिका|१३]] ∙ [[नेपालको_संविधान_२०७२#भाग-_१४_प्रदेश_व्यवस्थापिका|१४]] <br> [[नेपालको_संविधान_२०७२#भाग–१५_प्रादेशक_व्वस्थापन_कार्यविधि|१५]] ∙ [[नेपालको_संविधान_२०७२#भाग–१६_प्रादेशिक_आर्थिक_कार्यप्रणाली|१६]] ∙ [[नेपालको_संविधान_२०७२#भाग–१७_स्थानीय_कार्यपालिका|१७]] ∙ [[नेपालको_संविधान_२०७२#भाग–१८_स्थानीय_व्यवस्थापिका|१८]] ∙ [[नेपालको_संविधान_२०७२#भाग–१९_स्थानीय_आर्थिक_कार्यप्रणाली|१९]] ∙ [[नेपालको_संविधान_२०७२#भाग–२०_सङ्घ,_प्रदेश_र_स्थानीय_तह_वीच_अन्तरसम्बन्ध|२०]] ∙ [[अख्तियार दुरुपयोग अनुसन्धान आयोग, नेपाल|२१]] <br> [[महालेखापरीक्षकको कार्यालय (नेपाल)|२२]] ∙ [[लोक सेवा आयोग (नेपाल)|२३]] ∙ [[निर्वाचन आयोग (नेपाल)|२४]] ∙ [[राष्ट्रिय मानव अधिकार आयोग (नेपाल)|२५]] ∙ [[राष्ट्रिय प्राकृतिक स्रोत तथा वित्त आयोग, नेपाल|२६]] ∙ [[नेपालका संवैधानिक निकायहरू|२७]] ∙ २८ ∙ २९ ∙ ३० ∙ ३१ ∙ ३२ ∙ ३३ ∙ ३४ ∙ ३५ | list3title = [[नेपालको संविधान २०७२को धाराहरू|धाराहरू]] | list3 = | list4title = [[नेपालको संविधान २०७२ को अनुसूची|अनुसूची]] | list4 = [[नेपालको संविधान २०७२ को अनुसूची-१|१]] ∙ [[नेपालको संविधान २०७२ को अनुसूची-२|२]] ∙ [[नेपालको संविधान २०७२ को अनुसूची ३|३]] ∙ [[नेपालको संविधान २०७२ को अनुसूची ४|४]] ∙ [[नेपालको संविधान २०७२ को अनुसूची ५|५]]∙ [[नेपालको संविधान २०७२ को अनुसूची ६|६]]∙ [[नेपालको संविधान २०७२ को अनुसूची ७|७]]∙ [[नेपालको संविधान २०७२ को अनुसूची ८|८]]∙ [[नेपालको संविधान २०७२ को अनुसूची ९|९]] | list5title = [[नेपालको संविधान २०७२ को संशोधन|संशोधनहरू]] | list5 = [[नेपालको संविधानको पहिलो संशोधन, २०७२|पहिलो]] ∙ [[नेपालको संविधान दोस्रो संशोधन, २०७७|दोस्रो]] | list6title = सम्बन्धित लेख | list6 = {{Plainlist| * [[नेपालका प्रदेशहरू|प्रदेश]] * [[सङ्घ र प्रदेशको साझा अधिकारको सूची]] * [[Judicial review]] * [[मुलुकी अपराध संहिता, २०७४]] * [[मुलुकी देवानी संहिता]] }} }}<noinclude> [[Category:नेपालको संविधान|τ]] </noinclude> [[श्रेणी:नेपालको संविधान]] jwvpjsr3rm9zf25d95hiycsalzkbyz7 नेपालको संविधान २०७२ को संशोधन 0 135032 1361156 1280719 2026-06-11T12:22:54Z Bishaldev100 28807 /* सूची */ 1361156 wikitext text/x-wiki {{ढाँचा:नेपालको संविधान २०७२}} '''नेपालको संविधान संशोधन''' देशको सर्वोच्च कानूनमा सुधार गर्ने प्रक्रिया हो। संविधान संशोधन सम्बन्धि व्यवस्था [[नेपालको संविधान २०७२|यस संविधान]]को भाग ३१ मा उल्लेख गरिएको छ। यद्यपि सार्वभौमिकता, भौगोलिक अखण्डता, स्वाधीनता र जनतामा निहित सार्वभौमसत्ताको प्रतिकूल हुने गरी यो संविधान संशोधन गर्न अधिकार दिइएको छैन।<ref>{{Cite web |title=भाग–३१ संविधान संशोधन |url=https://lawcommission.gov.np/np/?p=871 |website=[[नेपाल कानुन आयोग]] }} {{Webarchive|url=https://web.archive.org/web/20230603162932/https://lawcommission.gov.np/np/?p=871 |date=2023-06-03 }}</ref> संसदमा पेश भएको संशोधन विधेयक [[नेपालको सङ्घीय संसद|संघीय संसद]]का दुबै सदनमा तत्काल कायम रहेका सम्पूर्ण सदस्य संख्याको कम्तीमा दुई तिहाइ बहुमतबाट पारित भएमा [[संविधान संशोधन]] हुनेछ। ==सूची== {| class="wikitable" |+ !सङ्ख्या !संशोधन !लागू भएको मिती !प्रधानमन्त्री !राष्ट्रपति !कडी |- |[[नेपालको संविधान पहिलो संशोधन, २०७२|पहिलो]] |धारा ४२, ८४, २८६ |२०७२ फागुन १६ | rowspan="2" |[[खड्गप्रसाद ओली|केपी ओली]] | rowspan="2" |[[विद्यादेवी भण्डारी]] |[https://www.moljpa.gov.np/wp-content/uploads/2018/02/नेपालको-संविधान-पहिलो-संशोधन२०७२.pdf पहिलो संशोधन] {{Webarchive|url=https://web.archive.org/web/20240220002708/https://www.moljpa.gov.np/wp-content/uploads/2018/02/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B5%E0%A4%BF%E0%A4%A7%E0%A4%BE%E0%A4%A8-%E0%A4%AA%E0%A4%B9%E0%A4%BF%E0%A4%B2%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B6%E0%A5%8B%E0%A4%A7%E0%A4%A8%E0%A5%A8%E0%A5%A6%E0%A5%AD%E0%A5%A8.pdf |date=2024-02-20 }} |- |[[नेपालको संविधान दोस्रो संशोधन विधेयक, २०७७|दोस्रो]] |[[नेपालको निसानछाप|अनुसूची ३]] |२०७७ असार ४ |[https://www.moljpa.gov.np/wp-content/uploads/2020/06/नेपालको-संविधान-दोस्रो-संशोधन-२०७७.pdf दोस्रो संशोधन] {{Webarchive|url=https://web.archive.org/web/20220809153033/http://www.moljpa.gov.np/wp-content/uploads/2020/06/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B5%E0%A4%BF%E0%A4%A7%E0%A4%BE%E0%A4%A8-%E0%A4%A6%E0%A5%8B%E0%A4%B8%E0%A5%8D%E0%A4%B0%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B6%E0%A5%8B%E0%A4%A7%E0%A4%A8-%E0%A5%A8%E0%A5%A6%E0%A5%AD%E0%A5%AD.pdf |date=2022-08-09 }} |} ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} ==बाह्य कडीहरू== * [https://lawcommission.gov.np/np/wp-content/uploads/2021/01/नेपालको-स%E2%80%8Cंविधान.pdf नेपालको संविधान २०७२] {{Webarchive|url=https://web.archive.org/web/20231114171056/https://lawcommission.gov.np/np/wp-content/uploads/2021/01/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A5%8B-%E0%A4%B8%E2%80%8C%E0%A4%82%E0%A4%B5%E0%A4%BF%E0%A4%A7%E0%A4%BE%E0%A4%A8.pdf |date=2023-11-14 }} * [https://www.moljpa.gov.np/wp-content/uploads/2018/02/नेपालको-संविधान-पहिलो-संशोधन२०७२.pdf नेपालको संविधान २०७२ को पहिलो संशोधन] {{Webarchive|url=https://web.archive.org/web/20240220002708/https://www.moljpa.gov.np/wp-content/uploads/2018/02/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B5%E0%A4%BF%E0%A4%A7%E0%A4%BE%E0%A4%A8-%E0%A4%AA%E0%A4%B9%E0%A4%BF%E0%A4%B2%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B6%E0%A5%8B%E0%A4%A7%E0%A4%A8%E0%A5%A8%E0%A5%A6%E0%A5%AD%E0%A5%A8.pdf |date=2024-02-20 }} * [https://www.moljpa.gov.np/wp-content/uploads/2020/06/नेपालको-संविधान-दोस्रो-संशोधन-२०७७.pdf नेपालको संविधान २०७२ को दोस्रो संशोधन] {{Webarchive|url=https://web.archive.org/web/20220809153033/http://www.moljpa.gov.np/wp-content/uploads/2020/06/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B5%E0%A4%BF%E0%A4%A7%E0%A4%BE%E0%A4%A8-%E0%A4%A6%E0%A5%8B%E0%A4%B8%E0%A5%8D%E0%A4%B0%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B6%E0%A5%8B%E0%A4%A7%E0%A4%A8-%E0%A5%A8%E0%A5%A6%E0%A5%AD%E0%A5%AD.pdf |date=2022-08-09 }} [[श्रेणी:नेपालको संविधान २०७२]] ev75rfyns94n8y0dbdsn5cn4xiu8ops 1361162 1361156 2026-06-11T13:22:56Z Bishaldev100 28807 /* सूची */ 1361162 wikitext text/x-wiki {{ढाँचा:नेपालको संविधान २०७२}} '''नेपालको संविधान संशोधन''' देशको सर्वोच्च कानूनमा सुधार गर्ने प्रक्रिया हो। संविधान संशोधन सम्बन्धि व्यवस्था [[नेपालको संविधान २०७२|यस संविधान]]को भाग ३१ मा उल्लेख गरिएको छ। यद्यपि सार्वभौमिकता, भौगोलिक अखण्डता, स्वाधीनता र जनतामा निहित सार्वभौमसत्ताको प्रतिकूल हुने गरी यो संविधान संशोधन गर्न अधिकार दिइएको छैन।<ref>{{Cite web |title=भाग–३१ संविधान संशोधन |url=https://lawcommission.gov.np/np/?p=871 |website=[[नेपाल कानुन आयोग]] }} {{Webarchive|url=https://web.archive.org/web/20230603162932/https://lawcommission.gov.np/np/?p=871 |date=2023-06-03 }}</ref> संसदमा पेश भएको संशोधन विधेयक [[नेपालको सङ्घीय संसद|संघीय संसद]]का दुबै सदनमा तत्काल कायम रहेका सम्पूर्ण सदस्य संख्याको कम्तीमा दुई तिहाइ बहुमतबाट पारित भएमा [[संविधान संशोधन]] हुनेछ। ==सूची== {| class="wikitable" |+ !सङ्ख्या !संशोधन !लागू भएको मिती !प्रधानमन्त्री !राष्ट्रपति !कडी |- |[[नेपालको संविधानको पहिलो संशोधन, २०७२|पहिलो]] |धारा ४२, ८४, २८६ |२०७२ फागुन १६ | rowspan="2" |[[खड्गप्रसाद ओली|केपी ओली]] | rowspan="2" |[[विद्यादेवी भण्डारी]] |[https://www.moljpa.gov.np/wp-content/uploads/2018/02/नेपालको-संविधान-पहिलो-संशोधन२०७२.pdf पहिलो संशोधन] {{Webarchive|url=https://web.archive.org/web/20240220002708/https://www.moljpa.gov.np/wp-content/uploads/2018/02/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B5%E0%A4%BF%E0%A4%A7%E0%A4%BE%E0%A4%A8-%E0%A4%AA%E0%A4%B9%E0%A4%BF%E0%A4%B2%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B6%E0%A5%8B%E0%A4%A7%E0%A4%A8%E0%A5%A8%E0%A5%A6%E0%A5%AD%E0%A5%A8.pdf |date=2024-02-20 }} |- |[[नेपालको संविधान दोस्रो संशोधन, २०७७|दोस्रो]] |[[नेपालको निसानछाप|अनुसूची ३]] |२०७७ असार ४ |[https://www.moljpa.gov.np/wp-content/uploads/2020/06/नेपालको-संविधान-दोस्रो-संशोधन-२०७७.pdf दोस्रो संशोधन] {{Webarchive|url=https://web.archive.org/web/20220809153033/http://www.moljpa.gov.np/wp-content/uploads/2020/06/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B5%E0%A4%BF%E0%A4%A7%E0%A4%BE%E0%A4%A8-%E0%A4%A6%E0%A5%8B%E0%A4%B8%E0%A5%8D%E0%A4%B0%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B6%E0%A5%8B%E0%A4%A7%E0%A4%A8-%E0%A5%A8%E0%A5%A6%E0%A5%AD%E0%A5%AD.pdf |date=2022-08-09 }} |} ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} ==बाह्य कडीहरू== * [https://lawcommission.gov.np/np/wp-content/uploads/2021/01/नेपालको-स%E2%80%8Cंविधान.pdf नेपालको संविधान २०७२] {{Webarchive|url=https://web.archive.org/web/20231114171056/https://lawcommission.gov.np/np/wp-content/uploads/2021/01/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A5%8B-%E0%A4%B8%E2%80%8C%E0%A4%82%E0%A4%B5%E0%A4%BF%E0%A4%A7%E0%A4%BE%E0%A4%A8.pdf |date=2023-11-14 }} * [https://www.moljpa.gov.np/wp-content/uploads/2018/02/नेपालको-संविधान-पहिलो-संशोधन२०७२.pdf नेपालको संविधान २०७२ को पहिलो संशोधन] {{Webarchive|url=https://web.archive.org/web/20240220002708/https://www.moljpa.gov.np/wp-content/uploads/2018/02/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B5%E0%A4%BF%E0%A4%A7%E0%A4%BE%E0%A4%A8-%E0%A4%AA%E0%A4%B9%E0%A4%BF%E0%A4%B2%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B6%E0%A5%8B%E0%A4%A7%E0%A4%A8%E0%A5%A8%E0%A5%A6%E0%A5%AD%E0%A5%A8.pdf |date=2024-02-20 }} * [https://www.moljpa.gov.np/wp-content/uploads/2020/06/नेपालको-संविधान-दोस्रो-संशोधन-२०७७.pdf नेपालको संविधान २०७२ को दोस्रो संशोधन] {{Webarchive|url=https://web.archive.org/web/20220809153033/http://www.moljpa.gov.np/wp-content/uploads/2020/06/%E0%A4%A8%E0%A5%87%E0%A4%AA%E0%A4%BE%E0%A4%B2%E0%A4%95%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B5%E0%A4%BF%E0%A4%A7%E0%A4%BE%E0%A4%A8-%E0%A4%A6%E0%A5%8B%E0%A4%B8%E0%A5%8D%E0%A4%B0%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%B6%E0%A5%8B%E0%A4%A7%E0%A4%A8-%E0%A5%A8%E0%A5%A6%E0%A5%AD%E0%A5%AD.pdf |date=2022-08-09 }} [[श्रेणी:नेपालको संविधान २०७२]] rounis1lhra36qxgefrbpnj2q3gjc7k सिलगढी (दर्जिलिङ) 0 139586 1361468 1216148 2026-06-12T08:54:38Z पर्वत सुवेदी 31224 /* */ 1361468 wikitext text/x-wiki #अनुप्रेषण [[सिलिगुडी]] p6wwx9dwzlloj68wglr0d0gwdbo313o नेवारी लिपि 0 141775 1361181 1353017 2026-06-12T01:56:25Z Jujubhaju 67302 Jujubhajuद्वारा [[प्रचलित लिपि]] पृष्ठलाई [[नेवारी लिपि]]मा सारियो: प्रचलित शीर्षक 1353017 wikitext text/x-wiki {{Infobox writing system | name = प्रचलित नेपाल | native_name = {{Script|Newa|𑐥𑑂𑐬𑐔𑐮𑐶𑐟 𑐣𑐾𑐥𑐵𑐮}}<ref name=Pandey2011>{{cite web|url=http://std.dkuug.dk/JTC1/SC2/WG2/docs/n4038.pdf|title=N4038: Preliminary Proposal to Encode the Prachalit Nepal Script in ISO/IEC 10646|first=Anshuman|last=Pandey|date=2011-05-03|access-date=2016-06-24}} {{Webarchive|url=https://web.archive.org/web/20160324065913/http://std.dkuug.dk/jtc1/sc2/wg2/docs/n4038.pdf |date=2016-03-24 }}</ref> | sample = Newar Varnamala.png | caption = | type = [[अक्षरात्मक लिपि|अक्षरात्मक]] | time = Unknown — 1769 | languages = [[नेवारी भाषा]], [[संस्कृत]], [[पाली भाषा|पाली]], [[मैथिली भाषा|मैथिली]] | fam1 = [[:en:Proto-Sinaitic alphabet|आद्य सिनैटिक वर्णमाला]] <sup>[a]</sup> | fam2 = [[:en:Phoenician alphabet|ध्वन्यामक वर्णमाला]] <sup>[a]</sup> | fam3 = [[:en:Aramaic alphabet|अरामैक वर्णमाला]] <sup>[a]</sup> | fam4 = [[ब्राह्मी लिपि]] | fam5 = [[गुप्त लिपि]] | fam6 = [[सिद्धम लिपि|सिद्धम]]<ref name="masica">{{cite book |last1=Masica |first1=Colin |title=The Indo-Aryan languages |date=1993 |page=143}}</ref> | fam7 = [[नेवारी लिपिहरू|नेवारी]] | sisters = [[रञ्जना लिपि|रञ्जना]]<br />[[भुजिमोल लिपि|भुजिमोल]] | iso15924 = Newa | unicode = [https://www.unicode.org/charts/PDF/U11400.pdf U+11400&ndash;U+1147F] | note = none }} <references /> [[File:Ghorashar_letterhead_1958.jpg|अङ्गुठाकार|200x200पिक्सेल|सन् ९५८मा ल्हासामा रहेको नेपाली व्यापारिक घरानाको पत्रको शीर्षकमा प्रयोग गरिएको नेपाल लिपि।]] [[File:Letter_in_nepal_script.jpg|अङ्गुठाकार|252x252पिक्सेल|नेपाल भाषा र नेपाल लिपिको ७ मे १९२४ को पत्र ल्हासा देखि काठमाडौँ पठाइएको थियो।]] नेवा, '''नेवार''', '''नेवारी''', वा '''नेपाल लिपि''' भनेर पनि चिनिने प्रचलित [[नेवारी लिपिहरू|नेपाली लिपि]] एक प्रकारको [[अक्षरात्मक लिपि|अबुगिदा]] लिपि हो। यो लिपि [[ब्राह्मी लिपि]] देखि आएको ब्राह्मी लिपिको परिवारको एक भाग हो। यस लिपि [[नेवारी भाषा|नेपाल भाषा]], [[संस्कृत]] र [[पाली भाषा|पाली]] लेख्न प्रयोग गरिएको थियो। ''[[सिक्किम]] हेराल्ड'' सिक्किम सरकारको बुलेटिन (नेवारी संस्करण) सहित विभिन्न प्रकाशनहरू अझै पनि यस लिपिमा प्रकाशित हुँदैछन्। ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} [[चित्र:Shukla Prachalit Nepal.svg|पाठ=|अङ्गुठाकार|प्रचालित नेपाल लिपिमा 'प्रचालित नेपाल' शब्द]] {{मैथिली भाषा}} [[श्रेणी:लिपि]] f3ftux2ci82fghhzoubqj2xcm7q69hh सेकेन्ड लेफ्टिनेन्ट 0 141824 1361173 1337281 2026-06-11T14:15:24Z Bishaldev100 28807 /* नेपाल */ 1361173 wikitext text/x-wiki अधिकांश [[सेना|सशस्त्र सेना]]मा, '''सेकेन्ड लेफ्टिनेन्ट''' जुनियर कमिशन्ड अधिकृत सैन्य पद हो। यो सामान्यतया [[उपसेनानी|लेफ्टिनेन्ट]] वा फर्स्ट लेफ्टिनेन्टभन्दा तल राखिन्छ। == अष्ट्रेलिया == अस्ट्रेलियाली सेनामा सेकेन्ड लेफ्टिनेन्टको पद सन् १९८६ सम्म अस्तित्वमा थियो। == संयुक्त अधिराज्य र अन्य राष्ट्रमण्डल देशहरू == सेकेन्ड लेफ्टिनेन्टको पद (2Lt) सन् १८७७ मा ब्रिटिस सेना मा सुरु भएको थियो । [[सहायक सेनानी|सब-लेफ्टिनेन्ट]] अल्पकालीन पदलाई प्रतिस्थापन गर्न सुरु गरिएको थियो, यो श्रेणी सन् १८८१ मा समाप्त भयो तर सन् १८८७ मा पुनः प्रस्तुत गरियो। <ref>{{cite book|last1=Roper|first1=Michael|title=The Records of the War Office and Related Departments, 1660-1964|date=1998|publisher=Public Record Office|isbn=978-1-873162-45-3|url=https://books.google.com/books?id=aKFRAQAAMAAJ|language=en|page=271}}</ref> == संयुक्त राज्य अमेरिका == [[चित्र:US-O1_insignia.svg|अङ्गुठाकार|175x175पिक्सेल|संयुक्त राज्य अमेरिकाको सशस्त्र बलको दोस्रो लेफ्टिनेन्ट दर्ज्यानी चिन्ह।]] [[संयुक्त राज्य अमेरिका]]मा, सेकेन्ड लेफ्टिनेन्ट [[संयुक्त राज्य अमेरिकी सेना|सेना]], मरीन कर्प्स, एयर फोर्स, र स्पेस फोर्स अधिकांश कमिशन्ड अफिसरहरूका लागि प्रवेश-स्तरको पद हो। == बङ्गलादेश == [[बङ्गलादेशी सेना|बङ्गलादेश सेना]] र बङ्गलादेश नौसेना मुक्ति युद्धदेखि नै सेकेन्ड लेफ्टिनेन्टको पद रहेको छ। यो [[लेफ्टिनेन्ट]] भन्दा तलको र मास्टर वारेन्ट अफिसर भन्दा माथिको पद हो। सेनामा,सेकेन्ड लेफ्टिनेन्टले इकाइमा प्रशासनिक अधिकारी वा स्टाफ अफिसरको रूपमा काम गर्दछ।<ref>{{cite web |title=Ranks & Insignia |url=https://join.army.mil.bd/home/page/ranks-insignia |website=Bangladesh Army }} {{Webarchive|url=https://web.archive.org/web/20241127115142/https://join.army.mil.bd/home/page/ranks-insignia |date=2024-11-27 }}</ref> नौसेनामा सेकेन्ड लेफ्टिनेन्टको पद छैन। यसको समकक्ष [[सहायक सेनानी|उप-लेफ्टिनेन्ट]] हुन्छ। <ref>{{Cite web |title=Rank & Insignia |url=https://joinnavy.navy.mil.bd/Rankandinsignia/ |website=Bangladesh Navy}}</ref> == नेपाल == {{मुख्य|नेपालको सैन्य दर्जा|सहायक सेनानी}} [[नेपाली सेना]] सेकेन्ड लेफ्टिनेन्ट बराबरको दर्जालाई [[सहायक सेनानी]] भनिन्छ । == सन्दर्भहरू == {{Reflist}} 28vk47tsycm4bh57whdgbzenfc0w8op क्रिमिया 0 143722 1361193 1278886 2026-06-12T05:38:52Z Bishaldev100 28807 1361193 wikitext text/x-wiki {{Infobox islands |name=क्रिमिया प्रायद्वीप |local_name= |image_name=[[File:Map of the Crimea.png|240px]]<br>Map of the Crimean Peninsula <br /><br /> {{Switcher|[[File:Flag of Crimea (Latest version).svg|220px]]|Flag of the [[Republic of Crimea (Russia)|Republic of Crimea]]|[[File:Flag of Crimea.svg|220px]]|Flag of the [[Autonomous Republic of Crimea]]}}|image_alt=|map_image=Crimea (orthographic projection).svg|map_size=220|location=[[Eastern Europe]]|waterbody={{ubl|[[Black Sea]]|[[Sea of Azov]]}}|coordinates={{Coord|45.3|34.4|scale:2000000_region:UA-43|display=inline,title}}|area_km2=27000|highest_mount=[[Roman-Kosh]]|elevation_m=1545|country={{sp}}|country_admin_divisions_title=[[Political status of Crimea|Status]]|country_admin_divisions=[[United Nations General Assembly Resolution 68/262|Internationally recognized]] as Ukrainian territory occupied by [[Russia]] (''see [[Political status of Crimea]]'')|country1=<!--Note: Do not add flag icons for geographic articles per MOS:INFOBOXFLAG-->Ukraine (de jure but not in control)|country1_admin_divisions_title=[[Territorial dispute|Contested]] regions|country1_admin_divisions_1=Northern Arabat Spit ([[Henichesk Raion]])<br />[[Autonomous Republic of Crimea]]<br />[[Sevastopol]]|country1_largest_city=[[Sevastopol]]|country2=<!--Note: Do not add flag icons for geographic articles per MOS:INFOBOXFLAG-->Russia (de facto control)|country2_admin_divisions_title=[[Territorial dispute|Contested]] regions|country2_admin_divisions_1=[[Republic of Crimea (Russia)|Republic of Crimea]]<br />[[Sevastopol]]|country2_largest_city=[[Sevastopol]]|demonym=[[Crimean people|Crimean]]|population={{increase}} 2,416,856<ref name="pop">{{cite web|url=https://rosstat.gov.ru/storage/mediabank/of43wDjn/PrPopul2021_Site.xls|format=XLS|script-title=ru:Численность населения Российской Федерации по муниципальным образованиям на 1 января 2021 года|trans-title=The population of the Russian Federation by municipalities as of January 1, 2021|language=ru|work=[[Russian Federal State Statistics Service]]|access-date=31 January 2021|archive-date=4 February 2021|archive-url=https://web.archive.org/web/20210204121301/https://rosstat.gov.ru/storage/mediabank/of43wDjn/PrPopul2021_Site.xls|url-status=dead}} {{Webarchive|url=https://web.archive.org/web/20210204121301/https://rosstat.gov.ru/storage/mediabank/of43wDjn/PrPopul2021_Site.xls |date=4 February 2021 }}</ref>|population_as_of=2021|utc_offset=+3|density_km2=84.6|iso_code=UA-43}} [[चित्र:Satellite_picture_of_Crimea,_Terra-MODIS,_05-16-2015.jpg|अङ्गुठाकार|मई 2015 क्रीमियन प्रायद्वीपको उपग्रह छवि]] [[क्रिमिया]] (/kraɪˈmiːə/i {{Respell|kry|MEE|ə}}) [[पूर्वी युरोप]]मा रहेको एउटा [[प्रायद्वीप]] हो, जुन [[कृष्ण सागर]]को उत्तरी किनारमा अवस्थित छ। यो [[कृष्ण सागर]] र सानो आजोभ सागरले लगभग पूर्ण रूपमा घेरिएको छ। पेरिकोपको थलप्राय द्वीपले क्रिमियालाई यूक्रेनको खेरसोन ओब्लास्टसँग जोड्छ। पूर्वतर्फ, सन् २०१८ मा निर्माण गरिएको क्रिमियन पुल केर्‍च जलडमरू मध्यमार्फत क्राइमियालाई रसियाको क्रास्नोदार क्राइसँग जोड्छ। उत्तरपूर्वमा रहेको अरबात स्पिट एक साँघुरो भूबाग हो, जसले सिवास लागुनहरूलाई आजोभ सागरबाट छुट्याउँछ। कालो सागरको पारिपट्टि पश्चिममा [[रोमानिया]] र दक्षिणमा [[टर्की]] अवस्थित छन्। क्रिमियाको जनसंख्या २.४ मिलियन छ, र यसको सबैभन्दा ठूलो सहर सेभास्टोपोल हो। यो क्षेत्र अन्तर्राष्ट्रिय रूपमा [[युक्रेन|यूक्रेन]]को भागको रूपमा मान्यता प्राप्त भए पनि, सन् २०१४ देखि रुसको कब्जामा रहेको छ। प्रारम्भिक आधुनिक कालसम्म टाउरिक प्रायद्वीप भनेर चिनिने क्राइमिया ऐतिहासिक रूपमा शास्त्रीय सभ्यता र स्टेप्पे क्षेत्रको सीमामा रहेको थियो। ग्रीकहरूले यसको दक्षिणी भाग उपनिवेश बनाए, जसलाई पछि रोमन र बाइजेन्टाइन साम्राज्यहरू तथा तिनका उत्तराधिकारी राज्यहरूले समाहित गरे, यद्यपि ग्रीक संस्कृति यथावत् रह्यो। केही सहरहरू जेनेवाका व्यापारिक उपनिवेश बने, तर पछि तिनीहरूलाई [[अटोमन साम्राज्य|ओटोमन साम्राज्य]]ले अधीनमा लियो। यस अवधिमा, आन्तरिक भाग विभिन्न स्टेप्पे घुमन्ते जातिहरूले ओगटेका थिए, र १३औँ शताब्दीमा सुनौलो हर्डको नियन्त्रणमा आयो, जसबाट क्रिमियाली खानते उत्तराधिकारी राज्यको रूपमा उदायो। १५औँ शताब्दीमा, क्राइमियाली खानते ओटोमन साम्राज्यको आश्रित राज्य बन्यो। रुस र पोल्यान्ड-लिथुआनियाद्वारा नियन्त्रण गरिएका भूमिहरू प्रायः यस अवधिमा गुलाम आक्रमणहरूको लक्ष्य बन्थे। १७८३ मा, रुस-टर्की युद्ध (१७६८–१७७४) पछि, [[रुसी साम्राज्य]]ले क्रिमियालाई गाभ्यो। क्रिमियाको रणनीतिक अवस्थाका कारण १८५४ को क्रिमियाली युद्ध भयो, साथै १९१७ को रुसी क्रान्ति पछि छोटो समय टिक्ने विभिन्न शासनहरू देखा परे। जब [[अक्टोबर क्रान्ति|बोल्शेविक]]हरूले क्रिमियालाई आफ्नो नियन्त्रणमा लिए, यसलाई रुसी सोभियत महासंघीय समाजवादी गणतन्त्रको एक स्वायत्त सोभियत गणतन्त्र बनाइयो। [[दोस्रो विश्वयुद्ध]]को समयमा, क्रिमिया जर्मनीद्वारा ओगटियो। १९४४ मा, सोभियतहरूले क्रिमिया पुनः नियन्त्रणमा लिएपछि, [[जोसेफ स्टालिन]]को आदेशमा क्राइमियाली टाटारहरूलाई जातीय रूपमा सफाया गर्दै निर्वासनमा पठाइयो, जसलाई सांस्कृतिक नरसंहारको रूपमा वर्णन गरिएको छ। १९४५ मा, क्रिमियालाई ओब्लास्टमा घटाइयो। १९५४ मा, सोभियत संघले १६५४ को पेरेयास्लाव सन्धिको ३००औँ वार्षिकीको अवसरमा, क्रिमियालाई युक्रेनी सोभियत समाजवादी गणतन्त्रमा हस्तान्तरण गर्यो। सन् १९९१ मा युक्रेनी स्वतन्त्रता पछि प्रायद्वीपको अधिकांश भागलाई क्रिमियाको स्वायत्त गणतन्त्रको रूपमा पुनर्गठित गरियो। क्रिमियामा सोभियत फ्लीट विवादमा थियो, तर सन् १९९७ को सन्धिले रसियालाई सेभास्तोपोलमा आफ्नो फ्लीटलाई आधार बनाउन अनुमति दियो। सन् २०१४ मा, प्रायद्वीप रूसी सेना कब्जा गरिएको थियो र रसियाले कब्जा गरेको थियो, तर अधिकांश देशहरूले क्रिमियालाई युक्रेनी क्षेत्रको रूपमा मान्यता दिएका छन्।<ref name="INTLCOM">{{Cite web |date=23 August 2021 |title=Ukraine's president pledges to 'return' Russia-annexed Crimea |url=https://www.aljazeera.com/news/2021/8/23/ukraines-president-pledges-to-return-russia-annexed-crimea |access-date=2024-06-27 |website=[[Al Jazeera Media Network|Al Jazeera]] |language=en}}</ref> == सन्दर्भ सामग्रीहरू == {{Reflist}} [[श्रेणी:युरोपका प्रयद्वीपहरू]] cau35sy9sn5ctwraetg9eoyf9l1rexv 1361194 1361193 2026-06-12T05:42:13Z Bishaldev100 28807 1361194 wikitext text/x-wiki {{Infobox islands |name=क्रिमिया प्रायद्वीप |local_name= |image_name=[[File:Map of the Crimea.png|240px]]<br>Map of the Crimean Peninsula <br /><br /> {{Switcher|[[File:Flag of Crimea (Latest version).svg|220px]]|Flag of the [[Republic of Crimea (Russia)|Republic of Crimea]]|[[File:Flag of Crimea.svg|220px]]|Flag of the [[Autonomous Republic of Crimea]]}}|image_alt=|map_image=Crimea (orthographic projection).svg|map_size=220|location=[[Eastern Europe]]|waterbody={{ubl|[[Black Sea]]|[[Sea of Azov]]}}|coordinates={{Coord|45.3|34.4|scale:2000000_region:UA-43|display=inline,title}}|area_km2=27000|highest_mount=[[Roman-Kosh]]|elevation_m=1545|country={{sp}}|country_admin_divisions_title=[[Political status of Crimea|Status]]|country_admin_divisions=[[United Nations General Assembly Resolution 68/262|Internationally recognized]] as Ukrainian territory occupied by [[Russia]] (''see [[Political status of Crimea]]'')|country1=<!--Note: Do not add flag icons for geographic articles per MOS:INFOBOXFLAG-->Ukraine (de jure but not in control)|country1_admin_divisions_title=[[Territorial dispute|Contested]] regions|country1_admin_divisions_1=Northern Arabat Spit ([[Henichesk Raion]])<br />[[Autonomous Republic of Crimea]]<br />[[Sevastopol]]|country1_largest_city=[[Sevastopol]]|country2=<!--Note: Do not add flag icons for geographic articles per MOS:INFOBOXFLAG-->Russia (de facto control)|country2_admin_divisions_title=[[Territorial dispute|Contested]] regions|country2_admin_divisions_1=[[Republic of Crimea (Russia)|Republic of Crimea]]<br />[[Sevastopol]]|country2_largest_city=[[Sevastopol]]|demonym=[[Crimean people|Crimean]]|population={{increase}} 2,416,856<ref name="pop">{{cite web|url=https://rosstat.gov.ru/storage/mediabank/of43wDjn/PrPopul2021_Site.xls|format=XLS|script-title=ru:Численность населения Российской Федерации по муниципальным образованиям на 1 января 2021 года|trans-title=The population of the Russian Federation by municipalities as of January 1, 2021|language=ru|work=[[Russian Federal State Statistics Service]]|access-date=31 January 2021|archive-date=4 February 2021|archive-url=https://web.archive.org/web/20210204121301/https://rosstat.gov.ru/storage/mediabank/of43wDjn/PrPopul2021_Site.xls|url-status=dead}} {{Webarchive|url=https://web.archive.org/web/20210204121301/https://rosstat.gov.ru/storage/mediabank/of43wDjn/PrPopul2021_Site.xls |date=4 February 2021 }}</ref>|population_as_of=2021|utc_offset=+3|density_km2=84.6|iso_code=UA-43}} [[चित्र:Satellite_picture_of_Crimea,_Terra-MODIS,_05-16-2015.jpg|अङ्गुठाकार|मई 2015 क्रीमियन प्रायद्वीपको उपग्रह छवि]] [[क्रिमिया]] (/kraɪˈmiːə/i {{Respell|kry|MEE|ə}}) [[पूर्वी युरोप]]मा रहेको एउटा [[प्रायद्वीप]] हो, जुन [[कृष्ण सागर]]को उत्तरी किनारमा अवस्थित छ। यो [[कृष्ण सागर]] र सानो आजोभ सागरले लगभग पूर्ण रूपमा घेरिएको छ। पेरिकोपको थलप्राय द्वीपले क्रिमियालाई यूक्रेनको खेरसोन ओब्लास्टसँग जोड्छ। पूर्वतर्फ, सन् २०१८ मा निर्माण गरिएको क्रिमियन पुल केर्‍च जलडमरू मध्यमार्फत क्राइमियालाई रसियाको क्रास्नोदार क्राइसँग जोड्छ। उत्तरपूर्वमा रहेको अरबात स्पिट एक साँघुरो भूबाग हो, जसले सिवास लागुनहरूलाई आजोभ सागरबाट छुट्याउँछ। कालो सागरको पारिपट्टि पश्चिममा [[रोमानिया]] र दक्षिणमा [[टर्की]] अवस्थित छन्। क्रिमियाको जनसंख्या २.४ मिलियन छ, र यसको सबैभन्दा ठूलो सहर सेभास्टोपोल हो। यो क्षेत्र अन्तर्राष्ट्रिय रूपमा [[युक्रेन|यूक्रेन]]को भागको रूपमा मान्यता प्राप्त भए पनि, सन् २०१४ देखि रुसको कब्जामा रहेको छ। प्रारम्भिक आधुनिक कालसम्म टाउरिक प्रायद्वीप भनेर चिनिने क्राइमिया ऐतिहासिक रूपमा शास्त्रीय सभ्यता र स्टेप्पे क्षेत्रको सीमामा रहेको थियो। ग्रीकहरूले यसको दक्षिणी भाग उपनिवेश बनाए, जसलाई पछि रोमन र बाइजेन्टाइन साम्राज्यहरू तथा तिनका उत्तराधिकारी राज्यहरूले समाहित गरे, यद्यपि ग्रीक संस्कृति यथावत् रह्यो। केही सहरहरू जेनेवाका व्यापारिक उपनिवेश बने, तर पछि तिनीहरूलाई [[अटोमन साम्राज्य|ओटोमन साम्राज्य]]ले अधीनमा लियो। यस अवधिमा, आन्तरिक भाग विभिन्न स्टेप्पे घुमन्ते जातिहरूले ओगटेका थिए, र १३औँ शताब्दीमा सुनौलो हर्डको नियन्त्रणमा आयो, जसबाट क्रिमियाली खानते उत्तराधिकारी राज्यको रूपमा उदायो। १५औँ शताब्दीमा, क्राइमियाली खानते ओटोमन साम्राज्यको आश्रित राज्य बन्यो। रुस र पोल्यान्ड-लिथुआनियाद्वारा नियन्त्रण गरिएका भूमिहरू प्रायः यस अवधिमा गुलाम आक्रमणहरूको लक्ष्य बन्थे। १७८३ मा, रुस-टर्की युद्ध (१७६८–१७७४) पछि, [[रुसी साम्राज्य]]ले क्रिमियालाई गाभ्यो। क्रिमियाको रणनीतिक अवस्थाका कारण १८५४ को क्रिमियाली युद्ध भयो, साथै १९१७ को रुसी क्रान्ति पछि छोटो समय टिक्ने विभिन्न शासनहरू देखा परे। जब [[अक्टोबर क्रान्ति|बोल्शेविक]]हरूले क्रिमियालाई आफ्नो नियन्त्रणमा लिए, यसलाई रुसी सोभियत महासंघीय समाजवादी गणतन्त्रको एक स्वायत्त सोभियत गणतन्त्र बनाइयो। [[दोस्रो विश्वयुद्ध]]को समयमा, क्रिमिया जर्मनीद्वारा ओगटियो। १९४४ मा, सोभियतहरूले क्रिमिया पुनः नियन्त्रणमा लिएपछि, [[जोसेफ स्टालिन]]को आदेशमा क्राइमियाली टाटारहरूलाई जातीय रूपमा सफाया गर्दै निर्वासनमा पठाइयो, जसलाई सांस्कृतिक नरसंहारको रूपमा वर्णन गरिएको छ। १९४५ मा, क्रिमियालाई ओब्लास्टमा घटाइयो। १९५४ मा, सोभियत संघले १६५४ को पेरेयास्लाव सन्धिको ३००औँ वार्षिकीको अवसरमा, क्रिमियालाई युक्रेनी सोभियत समाजवादी गणतन्त्रमा हस्तान्तरण गर्यो। सन् १९९१ मा युक्रेनी स्वतन्त्रता पछि प्रायद्वीपको अधिकांश भागलाई क्रिमियाको स्वायत्त गणतन्त्रको रूपमा पुनर्गठित गरियो। क्रिमियामा सोभियत फ्लीट विवादमा थियो, तर सन् १९९७ को सन्धिले रसियालाई सेभास्तोपोलमा आफ्नो फ्लीटलाई आधार बनाउन अनुमति दियो। सन् २०१४ मा, प्रायद्वीप रूसी सेना कब्जा गरिएको थियो र रसियाले कब्जा गरेको थियो, तर अधिकांश देशहरूले क्रिमियालाई युक्रेनी क्षेत्रको रूपमा मान्यता दिएका छन्।<ref name="INTLCOM">{{Cite web |date=23 August 2021 |title=Ukraine's president pledges to 'return' Russia-annexed Crimea |url=https://www.aljazeera.com/news/2021/8/23/ukraines-president-pledges-to-return-russia-annexed-crimea |access-date=2024-06-27 |website=[[Al Jazeera Media Network|Al Jazeera]] |language=en}}</ref> ==यो पनि हेर्नुहोस्== * [[रुस-युक्रेन युद्ध]] * [[रूसद्वारा क्रिमियाको बिलय]] * [[२०२१-२०२२ रुस-युक्रेन सङ्कट]] == सन्दर्भ सामग्रीहरू == {{Reflist}} [[श्रेणी:युरोपका प्रयद्वीपहरू]] gb9141esovl5vq4rygtnpw23ozaa5wu जे बी टुहुरे 0 143831 1361480 1279216 2026-06-12T10:54:37Z Janak Bhatta 10885 विकिकरण गर्नुपर्ने 1361480 wikitext text/x-wiki {{विकिकरण}} जेबी टुहुरे जन्म:- वि.सं. २००१ धरान,सुनसरी नेपाल पेसा:- गायक, राजनितिज्ञ मृत्यु:- वि.सं. २०७८ भदौ १० काठमाडौँ नेपाल जुथबहादुर खडगी (नेपालः जूठबहादुर खडगी) (नेपालः जे. बी. टुहुरे वि.सं. २००१ -वि.सं. २०७८ भदौ १०)(२६ अगस्ट २०२१), जसलाई जे. बी टुहुरे नामले पनि चिनिन्छ, एक नेपाली गायक तथा [[नेपालको व्यवस्थापिका संसद|संसद सदस्य]] (नेपालः संसद सदस्य) थिए। उनलाई जनगायक (जनताको गायक) को उपाधि दिइएको थियो किनभने उनले क्रान्तिकारी गीतहरू गाए र उनले १५० भन्दा बढी गीतहरू रेकर्ड गरे। <ref>{{Cite web |title=Folk singer JB Tuhure passes away |url=https://english.khabarhub.com/2021/26/205353/ |url-status=live |archive-url=https://web.archive.org/web/20210826103815/https://english.khabarhub.com/2021/26/205353/ |archive-date=26 August 2021 |access-date=26 August 2021 |website=Khabarhub |language=en}}</ref> ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} ==बाह्य कडीहरू== {{ठुटो}} [[श्रेणी:नेपालको दोस्रो संविधान सभाका सदस्यहरू]] [[श्रेणी:नेपाल कम्युनिस्ट पार्टी (माओवादी केन्द्र)का राजनीतिज्ञहरू]] [[श्रेणी:माओवादी जनयुद्धका मानिसहरू]] [[श्रेणी:सन् २०२१ मा मृत्यु]] l866kwejdgbzwg0isw8etf6phlisvp7 सोडियम 0 150068 1361195 1354735 2026-06-12T05:45:12Z Bishaldev100 28807 1361195 wikitext text/x-wiki '''सोडियम''' एक [[रसायनिक तत्व|रासायनिक तत्व]] हो-यसको [[रासायनिक सङ्केत|प्रतीक]] Na (ल्याटिन न्याट्रियमबाट) र [[परमाणु क्रमाङ्क|परमाणु सङ्ख्या]] ११ हुन्छ। यो एक नरम, चाँदी-सेतो, अत्यधिक प्रतिक्रियात्मक [[धातु]] हो। सोडियम एक अल्काली धातु हो, [[पेरियोडिक तालिका]]को ग्रुप १ मा रहेको छ। यसको एक मात्र स्थिर [[समस्थानिक|आइसोटोप]] <sup>23</sup> हो। यो धातु अत्यधिक प्रतिक्रियात्मक हुने भएकाले स्वतन्त्र रुपमा प्रकृतिमा पाइँदैन र यौगिकहरूबाट अलग गर्नुपर्छ। सोडियम [[पृथ्वी|पृथ्वीको]] सतहमा छैटौं सबैभन्दा प्रचुर तत्व हो । फेल्डस्पार्स, सोडालाइट, र हलाइट (NaCl) जस्ता धेरै [[खनिज]]को रुपमा प्रचुर मात्रामा पाइन्छ। सोडियमका धेरै लवणहरू पानीमा अत्यधिक घुलनशील हुन्छन्ः सोडियम आयनहरू युगौ देखि पृथ्वीका खनिजहरूबाट पानीको क्रियाबाट घुल्दै आएका छन्।, र यसैले सोडियम र [[क्लोरिन]] महासागरहरूमा वजनको आधारमा सबैभन्दा आम घुलनशील तत्व हुन्।&nbsp;&nbsp; पहिलो पटक १८०७ मा हम्फ्री डेभीले सोडियमलाई सोडियम हाइड्रोक्साइडको इलेक्ट्रोलिसिसद्वारा अलग गरेका थिए। अन्य धेरै उपयोगी सोडियम यौगिकहरू मध्ये, सोडियम हाइड्रोक्साइड [[साबुन|साबुन निर्माण]]को लागि प्रयोग गरिन्छ। [[सोडियम क्लोराइड]] (खाने योग्य नुन) एक डि-आइसिङ एजेन्ट र मानव सहित जनावरहरूका लागि एक पोषक तत्व हो। == प्रयोग == सोडियम धातुको महत्त्वपूर्ण प्रयोग उपयोगिता भनेको सोडियम यौगिकको प्रयोग हो। वार्षिक रूपमा लाखौँ टन [[सोडियम क्लोराइड]], हाइड्रोक्साइड र कार्बोनेट उत्पादन गरिन्छ। सोडियम क्लोराइड व्यापक रूपमा एन्टी-आइसिङ र डि-आइसिङ को लागि प्रयोग गरिन्छ र सोडियम बाइकार्बोनेटको प्रयोग बेकिङ, र सोडाब्लास्टिङ को लागि गरिन्छ। पोटासियमको साथसाथै, धेरै महत्त्वपूर्ण औषधिहरूमा जैव उपलब्धता सुधार गर्न सोडियम थप गरिन्छ, यद्यपि पोटेशियम धेरै जसो अवस्थामा राम्रो आयन हो, सोडियम कम मूल्य र आणविक वजनको लागि छानिन्छ।<ref>{{cite book|last=रेमिङ्टन|first=जोसेफ पि.|title=Remington: The Science and Practice of Pharmacy|date=2006|publisher=Lippincott Williams & Wilkins|isbn=978-0-7817-4673-1|pages=365–366|edition=21st|editor-last=बेरिङ्गर|editor-first=पल|oclc=60679584}}</ref> सोडियम हाइड्राइड विभिन्न प्रतिक्रियाहरूका लागि आधारको रूपमा प्रयोग गरिन्छ । === ताप स्थानान्तरण === तरल सोडियम ''सोडियम-कूल्ड फास्ट रिएक्टर''हरूमा ताप स्थानान्तरण तरल पदार्थको रूपमा प्रयोग गरिन्छ<ref name="sodiumcoolant">[http://www.ne.doe.gov/pdfFiles/SodiumCoolant_NRCpresentation.pdf Sodium as a Fast Reactor Coolant] {{webarchive|url=https://web.archive.org/web/20130113134710/http://www.ne.doe.gov/pdfFiles/SodiumCoolant_NRCpresentation.pdf|date=13 January 2013}} presented by Thomas H. Fanning. Nuclear Engineering Division. U.S. Department of Energy. U.S. Nuclear Regulatory Commission. Topical Seminar Series on Sodium Fast Reactors. 3 May 2007</ref> । यसमा उच्च थर्मल चालकता र रिएक्टरमा उच्च न्युट्रोन फ्लक्स प्राप्त गर्न आवश्यक न्युट्रॉन अवशोषण क्रस सेक्शन छ। सोडियमको उच्च उबलने बिन्दुले रिएक्टरलाई परिवेशमा सञ्चालन गर्न अनुमति दिन्छ (सामान्य दबाव, तर कमजोरीहरूमा यसको अपारदर्शिता समावेश छ, जसले दृश्य मर्मतसम्भारमा बाधा पुर्याउँछ, र यसको कडा रूपमा कम गर्ने गुणहरू। सोडियम पानीको सम्पर्कमा विस्फोट हुनेछ, यद्यपि यो हावामा बिस्तारै जलेको हुन्छ।<ref>{{Cite book|title=Fire and Explosion Hazards|page=363}}</ref> == सुरक्षा र सावधानी == {{Chembox|Section7={{Chembox Hazards | ExternalSDS = | GHSPictograms = {{GHS02}}{{GHS05}} | GHSSignalWord = Danger | HPhrases = {{H-phrases|260|314}} | PPhrases = {{P-phrases|223|231+232|280|305+351+338|370+378|422}}<ref>{{cite web|url=https://www.sigmaaldrich.com/catalog/product/aldrich/262714|title=Sodium 262714|website=Sigma-Aldrich|access-date=1 October 2018|archive-date=15 January 2016|archive-url=https://web.archive.org/web/20160115025601/http://www.sigmaaldrich.com/catalog/product/aldrich/262714|url-status=live}}</ref> | NFPA-H = 3 | NFPA-F = 1 | NFPA-R = 2 | NFPA-S = w | NFPA_ref =<ref>[http://www.ehs.neu.edu/laboratory_safety/general_information/nfpa_hazard_rating/documents/NFPAratingSZ.htm Hazard Rating Information for NFPA Fire Diamonds] {{webarchive|url=https://web.archive.org/web/20150217135922/http://www.ehs.neu.edu/laboratory_safety/general_information/nfpa_hazard_rating/documents/NFPAratingSZ.htm |date=17 February 2015 }}. Ehs.neu.edu. Retrieved on 11 November 2015.</ref> }}}}सोडियमले पानीको सम्पर्कमा प्रज्वालनशील [[हाइड्रोजन]] र कास्टिक सोडियम हाइड्रोक्साइड बनाउँछ;<ref>{{cite book|author1-link=|author=रोबर्ट अङेलिकी|title=Synthesis and Technique in Inorganic Chemistry|publisher=University Science Books|place=Mill Valley, CA|date=1999|isbn=978-0-935702-48-4}}</ref> निल्दा वा भिझेको छाला वा आँखाको सम्पर्कमा आउँदा गम्भीर जलन निम्त्याउन सक्छ।<ref name=":0">{{cite tech report|first=Routley J.|last=Gordon|title=Sodium explosion critically burns firefighters, Newton, Massachusetts|number=75|institution=[[United States Fire Administration]]|date=1993-10-25}}</ref><ref name="prudent">{{cite book|title=Prudent Practices in the Laboratory: Handling and Disposal of Chemicals|year=1995|url=https://archive.org/details/prudentpractices00coun_887|url-access=limited|author1=((U.S. National Research Council Committee on Prudent Practices for Handling, Storage, and Disposal of Chemicals in Laboratories))|publisher=National Academies|page=[https://archive.org/details/prudentpractices00coun_887/page/n403 390]|isbn=978-0-309-05229-0}}</ref> हाइड्रोजन (अत्यधिक विस्फोटक) र [[सोडियम हाइड्रोक्साइड]] (जुन पानीमा घुलनशील हुन्छ) पैदा हुने भएकाले पानीको उपस्थितिमा सोडियम स्वतः विस्फोट हुन्छ। यद्यपि, सोडियम हावाको सम्पर्कमा आउँदा र {{Cvt|290|C}}<ref>{{cite journal |last1=An |first1=Deukkwang |last2=Sunderland |first2=Peter B. |last3=Lathrop |first3=Daniel P. |date=2013 |title=Suppression of sodium fires with liquid nitrogen |url=http://terpconnect.umd.edu/~pbs/2013-An-et-al-FSJ.pdf |journal=Fire Safety Journal |volume=58 |pages=204–207 |bibcode=2013FirSJ..58..204A |doi=10.1016/j.firesaf.2013.02.001 |archive-url=https://web.archive.org/web/20170808160323/http://terpconnect.umd.edu/~pbs/2013-An-et-al-FSJ.pdf |archive-date=8 August 2017 }} {{Webarchive|url=https://web.archive.org/web/20170808160323/http://terpconnect.umd.edu/~pbs/2013-An-et-al-FSJ.pdf |date=8 August 2017 }}</ref> तापक्रम पुग्यो भने हल्का आगो देखिन्छ। ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} {{सानो पेरियोडिक तालिका}}{{Sodium compounds}} [[श्रेणी:तत्व]] [[श्रेणी:सङ्क्षिप्त विवरण भएका लेखहरू]] nd2y09ogr7h3ja2bv15bjbazgh1vt4n सोभियत विखण्डन 0 150437 1361467 1358049 2026-06-12T08:54:07Z पर्वत सुवेदी 31224 /* */ 1361467 wikitext text/x-wiki #अनुप्रेषण [[सोभियत सङ्घको विघटन]] nykcmug8r7l2wmuxqwp50drur3659an सोभियत सङ्घको विखण्डन 0 150460 1361466 1358334 2026-06-12T08:54:01Z पर्वत सुवेदी 31224 /* */ 1361466 wikitext text/x-wiki #अनुप्रेषण [[सोभियत सङ्घको विघटन]] nykcmug8r7l2wmuxqwp50drur3659an जर्मनी-नेपाल सम्बन्ध 0 150513 1361188 1361125 2026-06-12T04:45:05Z Bishaldev100 28807 1361188 wikitext text/x-wiki {| class="infobox" style="border-collapse:collapse;" |+ class="infobox-title" id="6" |नेपाल-जर्मनी सम्बन्ध | colspan="2" class="infobox-image" |[[File:Germany_Nepal_Locator.svg|250x250पिक्सेल|Map indicating locations of Germany and Nepal]] |- class="infobox-hiddenrow" ! colspan="2" class="infobox-header" style="background:lightgrey;color:inherit;" | |- style="height:0.6em" | style="background:#339933;color:inherit;" | | style="background:#E08020;color:inherit;" | |- ! scope="col" style="width:50%; text-align:center" |[[File:Flag_of_Germany.svg|कडी=|पाठ=|बोर्डर|50x50पिक्सेल]]<br />[[जर्मनी|जर्मनी]] ! scope="col" style="width:50%; text-align:center; border-left:thin solid lightgrey;" |[[File:Flag_of_Nepal.svg|कडी=|पाठ=|30x30पिक्सेल| ]]<br />[[नेपाल|नेपाल]] |} जर्मनी - नेपाल [[जर्मनी]] र [[नेपाल]] सम्बन्ध बिचको द्विपक्षीय सम्बन्ध हो।<ref>{{Cite web |last=Singh |first=Rishi |date=6 April 2008 |title=Nepal-German relations : Nepali perspectives and lessons |url=https://thehimalayantimes.com/opinion/nepal-german-relations-nepali-perspectives-and-lessons |access-date=11 October 2021 |website=The Himalayan Times |language=en}}</ref> १९३९ मा [[जर्मनीको चान्सलर|जर्मन चान्सलर]] एडल्फ हिटलरले [[त्रिभुवन वीरविक्रम शाह|राजा त्रिभुवन]]लाई मर्सिडिज बेन्ज उपहार दिएका थिए।<ref>{{Cite news|url=https://www.reuters.com/article/lifestyle/hitlers-car-gift-to-nepal-king-to-be-used-again-idUSTRE68F4P8/|title=Hitler's car gift to Nepal king to be used again|work=Reuters|access-date=2026-06-12|language=en-US}}</ref> [[दोस्रो विश्वयुद्ध]]मा, जर्मनी विरुद्ध [[युद्धको घोषणा]] गर्ने पहिलो देशहरू मध्ये नेपाल एक थियो। जर्मनले पोल्याण्डमाथि आक्रमण गरेको चौथो दिन ४ सेप्टेम्बर १९३९ मा युद्ध घोषणा गरेको थियो । ।<ref>{{Cite book|title=I Won't Be Home Next Summer: Flight Lieutenant R.N. Selley DFC (1917–1941)|url=https://books.google.com/books?id=AOiZBgAAQBAJ&pg=PA89|location=Pinetown|page=89}}</ref> जर्मनी-नेपाल सम्बन्ध आधिकारिक रूपमा ४ अप्रिल १९५८ मा स्थापित भएको थियो।<ref>{{Cite web |title=Nepal – Germany Relations |url=https://mofa.gov.np/nepal-germany-relations/ |access-date=11 October 2021 |website=Ministry of Foreign Affairs Nepal}}</ref> == व्यापार == सन् २०२२ मा, नेपालले जर्मनीमा ४३ मिलियन डलर बराबरको सामान निर्यात गर्‍यो, जसमध्ये सबैभन्दा ठूलो निर्यात कार्पेट थियो। जर्मनीले त्यही वर्ष नेपालमा ४७.३ मिलियन डलर बराबरको सामान निर्यात गर्‍यो, जसमध्ये सबैभन्दा ठूलो निर्यात रेजर ब्लेड थियो।<ref>{{Cite web |title=What does Nepal export to Germany (2022) |url=https://oec.world/en/visualize/tree_map/hs92/export/deu/npl/show/2022 |access-date=27 March 2024 |website=oec.world}}</ref> [[चित्र:German_Buddhist_Temple_(9105852247).jpg|अङ्गुठाकार|269x269पिक्सेल|[[लुम्बिनी|लुम्बिनी, नेपाल]] मा जर्मनीको बौद्ध मन्दिर]] ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} {{नेपालको परराष्ट्र सम्बन्ध}} [[श्रेणी:सङ्क्षिप्त विवरण भएका लेखहरू]] bg773806rvsfwa2a8ojl8ermfronj4m नेपालको संविधानको पहिलो संशोधन, २०७२ 0 150518 1361152 2026-06-11T12:21:14Z Bishaldev100 28807 नयाँ पृष्ठ: {{Infobox legislation |short_title = नेपालको संविधान पहिलो संशोधन, २०७७ |legislature = [[नेपालको सङ्घीय संसद|नेपालको संसद]] |image = |imagesize = 150px |imagealt = |caption = |long_title = |citation = [http://rajpatra.dop.gov.np/welcome/book/?ref=24111 दोस... 1361152 wikitext text/x-wiki {{Infobox legislation |short_title = नेपालको संविधान पहिलो संशोधन, २०७७ |legislature = [[नेपालको सङ्घीय संसद|नेपालको संसद]] |image = |imagesize = 150px |imagealt = |caption = |long_title = |citation = [http://rajpatra.dop.gov.np/welcome/book/?ref=24111 दोस्रो संशोधन] |territorial_extent = [[नेपाल]] |enacted_by = [[प्रतिनिधि सभा (नेपाल)|प्रतिनिधि सभा]] |date_passed = ०९ माघ २०७२ |enacted_by2 = [[राष्ट्रिय सभा (नेपाल)|राष्ट्रिय सभा]] |date_passed2 = ०९ माघ २०७२ |date_assented = |signed_by = [[विद्यादेवी भण्डारी]] |date_commenced = २०७२ फागुन १६ |date_repealed = |administered_by = |bill = नेपालको संविधान पहिलो संशोधन विधेयक, २०७२ |bill_citation = |bill_date = |introduced_by =[[खड्गप्रसाद ओली|केपी शर्मा ओली]] |1st_reading = |2nd_reading = |3rd_reading = |conf_committee_passed = |bill2 = |bill_citation2 = |bill_date2 = |introduced_by2 = |1st_reading2 = |2nd_reading2 = |3rd_reading2 = |conf_committee_passed2 = |date_conf_committee = |white_paper = |committee_report = |amendments = |repeals = |related_legislation = |summary = |keywords = |status = सक्रिय }} नेपालको संविधानको पहिलो संशोधन, २०७२ लाई २०७२ साल माघ ९ गतेको व्यवस्थापिका-संसद्ले दुई तिहाइ बहुमतले पारित गरेको थियो<ref>{{Cite web |last=शर्मा |first=ओम |date=०९ माघ २०७२ |title=संविधानको पहिलो संशोधन विधेयक पारित, पक्षमा ४६१ र विपक्षमा सात मत |url=https://www.ratopati.com/story/293461 |access-date= |website=www.ratopati.com |language=Nepali}}</ref><ref>{{Cite web |title=मधेसी मोर्चाको माग आंशिक सम्वोधन गर्दै संविधानमा पहिलो संशोधन, पक्षमा ४६१, विपक्षमा ७ मत |url=https://www.onlinekhabar.com/2016/01/378773/%e0%a4%ae%e0%a4%a7%e0%a5%87%e0%a4%b8%e0%a5%80-%e0%a4%ae%e0%a5%8b%e0%a4%b0%e0%a5%8d%e0%a4%9a%e0%a4%be%e0%a4%95%e0%a5%8b-%e0%a4%ae%e0%a4%be%e0%a4%97-%e0%a4%86%e0%a4%82%e0%a4%b6%e0%a4%bf%e0%a4%95 |access-date=2026-06-11 |website=Online Khabar |language=en-US}}</ref> र यो संशोधन २०७२ फागुन १६ गतेदेखि लागू भएको थियो। यो संशोधन तराई-मधेस आन्दोलनकारी दलका मागहरूलाई आंशिक रूपमा सम्बोधन गर्न ल्याइएको थियो। == संशोधन == {| class="wikitable" |+ !क्रम !धारा !विद्यमान !संशोधित |- |१ |धारा ४२ को उपधारा (१) | |आर्थिक, सामाजिक वा शैक्षिक दृष्टिले पछाडि परेका महिला दलित, आदिवासी जनजाति, मधेसी, थारू, मुस्लिम्, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |- |२ |धारा ८४ को उपधारा (१) को खण्ड (क) |नेपाललाई भूगोल र जनसंख्याको आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी पहिलो हुने निर्वाचित हुने निर्वाचन  प्रणाली बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |नेपाललाई जनसंख्या र भौगोलिक  अनुकुलता तथा विशिष्टता आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी पहिलो हुने निर्वाचित हुने निर्वाचन  प्रणाली बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |- |३ | २८६ उपधारा (५) | |निर्वाचन क्षेत्र निर्धारण आयोगबाट यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा धारा ८४ को उप धारा (१) को खण्ड (क) को अधीनमा रही प्रतिनिधित्वको लागी जनसंख्यालाई मुख्य र भूगोला लाई दोस्रो आधार मानी संघीय कानून बमोजिम प्रदेशमा निर्वाचन क्षेत्र निर्धारन गरिनेछ र प्रदेशभित्र रहेका प्रत्येक जिल्लामा कम्तीमा एक निर्वाचन क्षेत्र रहनेछन् । |- |४ |२८६ उपधारा (६) |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाईइ समेत ध्यान दिनु पर्नेछ। |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसङ्ख्या र भौगोलिक अनुकुलता, सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाईइ समेत ध्यान दिनु पर्नेछ । |} 6uu91va6kz3coxhei1c92qzj4w053w4 1361153 1361152 2026-06-11T12:21:28Z Bishaldev100 28807 1361153 wikitext text/x-wiki {{Infobox legislation |short_title = नेपालको संविधान पहिलो संशोधन, २०७७ |legislature = [[नेपालको सङ्घीय संसद|नेपालको संसद]] |image = |imagesize = 150px |imagealt = |caption = |long_title = |citation = [http://rajpatra.dop.gov.np/welcome/book/?ref=24111 दोस्रो संशोधन] |territorial_extent = [[नेपाल]] |enacted_by = [[प्रतिनिधि सभा (नेपाल)|प्रतिनिधि सभा]] |date_passed = ०९ माघ २०७२ |enacted_by2 = [[राष्ट्रिय सभा (नेपाल)|राष्ट्रिय सभा]] |date_passed2 = ०९ माघ २०७२ |date_assented = |signed_by = [[विद्यादेवी भण्डारी]] |date_commenced = २०७२ फागुन १६ |date_repealed = |administered_by = |bill = नेपालको संविधान पहिलो संशोधन विधेयक, २०७२ |bill_citation = |bill_date = |introduced_by =[[खड्गप्रसाद ओली|केपी शर्मा ओली]] |1st_reading = |2nd_reading = |3rd_reading = |conf_committee_passed = |bill2 = |bill_citation2 = |bill_date2 = |introduced_by2 = |1st_reading2 = |2nd_reading2 = |3rd_reading2 = |conf_committee_passed2 = |date_conf_committee = |white_paper = |committee_report = |amendments = |repeals = |related_legislation = |summary = |keywords = |status = सक्रिय }} नेपालको संविधानको पहिलो संशोधन, २०७२ लाई २०७२ साल माघ ९ गतेको व्यवस्थापिका-संसद्ले दुई तिहाइ बहुमतले पारित गरेको थियो<ref>{{Cite web |last=शर्मा |first=ओम |date=०९ माघ २०७२ |title=संविधानको पहिलो संशोधन विधेयक पारित, पक्षमा ४६१ र विपक्षमा सात मत |url=https://www.ratopati.com/story/293461 |access-date= |website=www.ratopati.com |language=Nepali}}</ref><ref>{{Cite web |title=मधेसी मोर्चाको माग आंशिक सम्वोधन गर्दै संविधानमा पहिलो संशोधन, पक्षमा ४६१, विपक्षमा ७ मत |url=https://www.onlinekhabar.com/2016/01/378773/%e0%a4%ae%e0%a4%a7%e0%a5%87%e0%a4%b8%e0%a5%80-%e0%a4%ae%e0%a5%8b%e0%a4%b0%e0%a5%8d%e0%a4%9a%e0%a4%be%e0%a4%95%e0%a5%8b-%e0%a4%ae%e0%a4%be%e0%a4%97-%e0%a4%86%e0%a4%82%e0%a4%b6%e0%a4%bf%e0%a4%95 |access-date=2026-06-11 |website=Online Khabar |language=en-US}}</ref> र यो संशोधन २०७२ फागुन १६ गतेदेखि लागू भएको थियो। यो संशोधन तराई-मधेस आन्दोलनकारी दलका मागहरूलाई आंशिक रूपमा सम्बोधन गर्न ल्याइएको थियो। == संशोधन == {| class="wikitable" |+ !क्रम !धारा !विद्यमान !संशोधित |- |१ |धारा ४२ को उपधारा (१) | |आर्थिक, सामाजिक वा शैक्षिक दृष्टिले पछाडि परेका महिला दलित, आदिवासी जनजाति, मधेसी, थारू, मुस्लिम्, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |- |२ |धारा ८४ को उपधारा (१) को खण्ड (क) |नेपाललाई भूगोल र जनसंख्याको आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी पहिलो हुने निर्वाचित हुने निर्वाचन  प्रणाली बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |नेपाललाई जनसंख्या र भौगोलिक  अनुकुलता तथा विशिष्टता आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी पहिलो हुने निर्वाचित हुने निर्वाचन  प्रणाली बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |- |३ | २८६ उपधारा (५) | |निर्वाचन क्षेत्र निर्धारण आयोगबाट यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा धारा ८४ को उप धारा (१) को खण्ड (क) को अधीनमा रही प्रतिनिधित्वको लागी जनसंख्यालाई मुख्य र भूगोला लाई दोस्रो आधार मानी संघीय कानून बमोजिम प्रदेशमा निर्वाचन क्षेत्र निर्धारन गरिनेछ र प्रदेशभित्र रहेका प्रत्येक जिल्लामा कम्तीमा एक निर्वाचन क्षेत्र रहनेछन् । |- |४ |२८६ उपधारा (६) |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाईइ समेत ध्यान दिनु पर्नेछ। |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसङ्ख्या र भौगोलिक अनुकुलता, सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाईइ समेत ध्यान दिनु पर्नेछ । |} ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} 32m64lyw94peapxn73hqhlhzvtbk9nf 1361154 1361153 2026-06-11T12:21:57Z Bishaldev100 28807 1361154 wikitext text/x-wiki {{Infobox legislation |short_title = नेपालको संविधान पहिलो संशोधन, २०७७ |legislature = [[नेपालको सङ्घीय संसद|नेपालको संसद]] |image = |imagesize = 150px |imagealt = |caption = |long_title = |citation = [http://rajpatra.dop.gov.np/welcome/book/?ref=24111 दोस्रो संशोधन] |territorial_extent = [[नेपाल]] |enacted_by = [[प्रतिनिधि सभा (नेपाल)|प्रतिनिधि सभा]] |date_passed = ०९ माघ २०७२ |enacted_by2 = [[राष्ट्रिय सभा (नेपाल)|राष्ट्रिय सभा]] |date_passed2 = ०९ माघ २०७२ |date_assented = |signed_by = [[विद्यादेवी भण्डारी]] |date_commenced = २०७२ फागुन १६ |date_repealed = |administered_by = |bill = नेपालको संविधान पहिलो संशोधन विधेयक, २०७२ |bill_citation = |bill_date = |introduced_by =[[खड्गप्रसाद ओली|केपी शर्मा ओली]] |1st_reading = |2nd_reading = |3rd_reading = |conf_committee_passed = |bill2 = |bill_citation2 = |bill_date2 = |introduced_by2 = |1st_reading2 = |2nd_reading2 = |3rd_reading2 = |conf_committee_passed2 = |date_conf_committee = |white_paper = |committee_report = |amendments = |repeals = |related_legislation = |summary = |keywords = |status = सक्रिय }} {{ढाँचा:नेपालको संविधान २०७२}} नेपालको संविधानको पहिलो संशोधन, २०७२ लाई २०७२ साल माघ ९ गतेको व्यवस्थापिका-संसद्ले दुई तिहाइ बहुमतले पारित गरेको थियो<ref>{{Cite web |last=शर्मा |first=ओम |date=०९ माघ २०७२ |title=संविधानको पहिलो संशोधन विधेयक पारित, पक्षमा ४६१ र विपक्षमा सात मत |url=https://www.ratopati.com/story/293461 |access-date= |website=www.ratopati.com |language=Nepali}}</ref><ref>{{Cite web |title=मधेसी मोर्चाको माग आंशिक सम्वोधन गर्दै संविधानमा पहिलो संशोधन, पक्षमा ४६१, विपक्षमा ७ मत |url=https://www.onlinekhabar.com/2016/01/378773/%e0%a4%ae%e0%a4%a7%e0%a5%87%e0%a4%b8%e0%a5%80-%e0%a4%ae%e0%a5%8b%e0%a4%b0%e0%a5%8d%e0%a4%9a%e0%a4%be%e0%a4%95%e0%a5%8b-%e0%a4%ae%e0%a4%be%e0%a4%97-%e0%a4%86%e0%a4%82%e0%a4%b6%e0%a4%bf%e0%a4%95 |access-date=2026-06-11 |website=Online Khabar |language=en-US}}</ref> र यो संशोधन २०७२ फागुन १६ गतेदेखि लागू भएको थियो। यो संशोधन तराई-मधेस आन्दोलनकारी दलका मागहरूलाई आंशिक रूपमा सम्बोधन गर्न ल्याइएको थियो। == संशोधन == {| class="wikitable" |+ !क्रम !धारा !विद्यमान !संशोधित |- |१ |धारा ४२ को उपधारा (१) | |आर्थिक, सामाजिक वा शैक्षिक दृष्टिले पछाडि परेका महिला दलित, आदिवासी जनजाति, मधेसी, थारू, मुस्लिम्, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |- |२ |धारा ८४ को उपधारा (१) को खण्ड (क) |नेपाललाई भूगोल र जनसंख्याको आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी पहिलो हुने निर्वाचित हुने निर्वाचन  प्रणाली बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |नेपाललाई जनसंख्या र भौगोलिक  अनुकुलता तथा विशिष्टता आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी पहिलो हुने निर्वाचित हुने निर्वाचन  प्रणाली बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |- |३ | २८६ उपधारा (५) | |निर्वाचन क्षेत्र निर्धारण आयोगबाट यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा धारा ८४ को उप धारा (१) को खण्ड (क) को अधीनमा रही प्रतिनिधित्वको लागी जनसंख्यालाई मुख्य र भूगोला लाई दोस्रो आधार मानी संघीय कानून बमोजिम प्रदेशमा निर्वाचन क्षेत्र निर्धारन गरिनेछ र प्रदेशभित्र रहेका प्रत्येक जिल्लामा कम्तीमा एक निर्वाचन क्षेत्र रहनेछन् । |- |४ |२८६ उपधारा (६) |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाईइ समेत ध्यान दिनु पर्नेछ। |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसङ्ख्या र भौगोलिक अनुकुलता, सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाईइ समेत ध्यान दिनु पर्नेछ । |} ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} od0qu9ynqtein5g5802gsi326dr8egk 1361158 1361154 2026-06-11T12:34:38Z Bishaldev100 28807 /* संशोधन */ 1361158 wikitext text/x-wiki {{Infobox legislation |short_title = नेपालको संविधान पहिलो संशोधन, २०७७ |legislature = [[नेपालको सङ्घीय संसद|नेपालको संसद]] |image = |imagesize = 150px |imagealt = |caption = |long_title = |citation = [http://rajpatra.dop.gov.np/welcome/book/?ref=24111 दोस्रो संशोधन] |territorial_extent = [[नेपाल]] |enacted_by = [[प्रतिनिधि सभा (नेपाल)|प्रतिनिधि सभा]] |date_passed = ०९ माघ २०७२ |enacted_by2 = [[राष्ट्रिय सभा (नेपाल)|राष्ट्रिय सभा]] |date_passed2 = ०९ माघ २०७२ |date_assented = |signed_by = [[विद्यादेवी भण्डारी]] |date_commenced = २०७२ फागुन १६ |date_repealed = |administered_by = |bill = नेपालको संविधान पहिलो संशोधन विधेयक, २०७२ |bill_citation = |bill_date = |introduced_by =[[खड्गप्रसाद ओली|केपी शर्मा ओली]] |1st_reading = |2nd_reading = |3rd_reading = |conf_committee_passed = |bill2 = |bill_citation2 = |bill_date2 = |introduced_by2 = |1st_reading2 = |2nd_reading2 = |3rd_reading2 = |conf_committee_passed2 = |date_conf_committee = |white_paper = |committee_report = |amendments = |repeals = |related_legislation = |summary = |keywords = |status = सक्रिय }} {{ढाँचा:नेपालको संविधान २०७२}} नेपालको संविधानको पहिलो संशोधन, २०७२ लाई २०७२ साल माघ ९ गतेको व्यवस्थापिका-संसद्ले दुई तिहाइ बहुमतले पारित गरेको थियो<ref>{{Cite web |last=शर्मा |first=ओम |date=०९ माघ २०७२ |title=संविधानको पहिलो संशोधन विधेयक पारित, पक्षमा ४६१ र विपक्षमा सात मत |url=https://www.ratopati.com/story/293461 |access-date= |website=www.ratopati.com |language=Nepali}}</ref><ref>{{Cite web |title=मधेसी मोर्चाको माग आंशिक सम्वोधन गर्दै संविधानमा पहिलो संशोधन, पक्षमा ४६१, विपक्षमा ७ मत |url=https://www.onlinekhabar.com/2016/01/378773/%e0%a4%ae%e0%a4%a7%e0%a5%87%e0%a4%b8%e0%a5%80-%e0%a4%ae%e0%a5%8b%e0%a4%b0%e0%a5%8d%e0%a4%9a%e0%a4%be%e0%a4%95%e0%a5%8b-%e0%a4%ae%e0%a4%be%e0%a4%97-%e0%a4%86%e0%a4%82%e0%a4%b6%e0%a4%bf%e0%a4%95 |access-date=2026-06-11 |website=Online Khabar |language=en-US}}</ref> र यो संशोधन २०७२ फागुन १६ गतेदेखि लागू भएको थियो। यो संशोधन तराई-मधेस आन्दोलनकारी दलका मागहरूलाई आंशिक रूपमा सम्बोधन गर्न ल्याइएको थियो। == संशोधन == {| class="wikitable" |+ !क्रम !धारा !विद्यमान<ref>{{Cite web |title=28. नेपालकाे संविधान |url=http://rajpatra.dop.gov.np/welcome/book/?ref=22517 |access-date=2026-06-11 |website=rajpatra.dop.gov.np}}</ref> !संशोधित<ref>{{Cite web |title=नेपालको संविधान (पहिलो संशोधन), २०७२ |url=https://www.moljpa.gov.np/public/uploads/c2cb256b-c748-4fc3-8e5c-ef08b94f0560.pdf}}</ref> |- |१ |धारा ४२ को उपधारा (१) |सामाजिक रूपले पछाडि परेका महिला, दलित, आदिवासी जनजाति, मधेशी, थारू, मुस्लिम, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |आर्थिक, सामाजिक वा शैक्षिक दृष्टिले पछाडि परेका महिला दलित, आदिवासी जनजाति, मधेसी, थारू, मुस्लिम, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |- |२ |धारा ८४ को उपधारा (१) को खण्ड (क) |नेपाललाई भूगोल र जनसंख्याको आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी पहिलो हुने निर्वाचित हुने निर्वाचन  प्रणाली बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |नेपाललाई जनसंख्या र भौगोलिक  अनुकुलता तथा विशिष्टता आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी [[पहिलो हुने निर्वाचित हुने निर्वाचन प्रणाली|पहिलो हुने निर्वाचित हुने]] निर्वाचन  प्रणाली बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |- |३ | २८६ उपधारा (५) |निर्वाचन क्षेत्र निर्धारण आयोगले यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसंख्या र भूगोल लाई प्रतिनिधित्वको आधारा मानी त्यस्तो निर्वाचन क्षेत्राजएए भूगोल, जनसंख्या र सदस्य संख्या बीचको अनुपात यथासम्भव समान हुने गरी निर्धारण गर्नेछ । |निर्वाचन क्षेत्र निर्धारण आयोगबाट यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा धारा ८४ को उपधारा (१) को खण्ड (क) को अधीनमा रही प्रतिनिधित्वको लागी जनसंख्यालाई मुख्य र भूगोला लाई दोस्रो आधार मानी संघीय कानून बमोजिम प्रदेशमा निर्वाचन क्षेत्र निर्धारन गरिनेछ र प्रदेशभित्र रहेका प्रत्येक जिल्लामा कम्तीमा एक निर्वाचन क्षेत्र रहनेछन् । |- |४ |२८६ उपधारा (६) |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाईइ समेत ध्यान दिनु पर्नेछ। |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसङ्ख्या र भौगोलिक अनुकुलता, सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाईइ समेत ध्यान दिनु पर्नेछ । |} ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} a3yjvz7aeq61rw0r0jli6fll9wcehx2 1361174 1361158 2026-06-11T14:28:48Z Bishaldev100 28807 /* संशोधन */ 1361174 wikitext text/x-wiki {{Infobox legislation |short_title = नेपालको संविधान पहिलो संशोधन, २०७७ |legislature = [[नेपालको सङ्घीय संसद|नेपालको संसद]] |image = |imagesize = 150px |imagealt = |caption = |long_title = |citation = [http://rajpatra.dop.gov.np/welcome/book/?ref=24111 दोस्रो संशोधन] |territorial_extent = [[नेपाल]] |enacted_by = [[प्रतिनिधि सभा (नेपाल)|प्रतिनिधि सभा]] |date_passed = ०९ माघ २०७२ |enacted_by2 = [[राष्ट्रिय सभा (नेपाल)|राष्ट्रिय सभा]] |date_passed2 = ०९ माघ २०७२ |date_assented = |signed_by = [[विद्यादेवी भण्डारी]] |date_commenced = २०७२ फागुन १६ |date_repealed = |administered_by = |bill = नेपालको संविधान पहिलो संशोधन विधेयक, २०७२ |bill_citation = |bill_date = |introduced_by =[[खड्गप्रसाद ओली|केपी शर्मा ओली]] |1st_reading = |2nd_reading = |3rd_reading = |conf_committee_passed = |bill2 = |bill_citation2 = |bill_date2 = |introduced_by2 = |1st_reading2 = |2nd_reading2 = |3rd_reading2 = |conf_committee_passed2 = |date_conf_committee = |white_paper = |committee_report = |amendments = |repeals = |related_legislation = |summary = |keywords = |status = सक्रिय }} {{ढाँचा:नेपालको संविधान २०७२}} नेपालको संविधानको पहिलो संशोधन, २०७२ लाई २०७२ साल माघ ९ गतेको व्यवस्थापिका-संसद्ले दुई तिहाइ बहुमतले पारित गरेको थियो<ref>{{Cite web |last=शर्मा |first=ओम |date=०९ माघ २०७२ |title=संविधानको पहिलो संशोधन विधेयक पारित, पक्षमा ४६१ र विपक्षमा सात मत |url=https://www.ratopati.com/story/293461 |access-date= |website=www.ratopati.com |language=Nepali}}</ref><ref>{{Cite web |title=मधेसी मोर्चाको माग आंशिक सम्वोधन गर्दै संविधानमा पहिलो संशोधन, पक्षमा ४६१, विपक्षमा ७ मत |url=https://www.onlinekhabar.com/2016/01/378773/%e0%a4%ae%e0%a4%a7%e0%a5%87%e0%a4%b8%e0%a5%80-%e0%a4%ae%e0%a5%8b%e0%a4%b0%e0%a5%8d%e0%a4%9a%e0%a4%be%e0%a4%95%e0%a5%8b-%e0%a4%ae%e0%a4%be%e0%a4%97-%e0%a4%86%e0%a4%82%e0%a4%b6%e0%a4%bf%e0%a4%95 |access-date=2026-06-11 |website=Online Khabar |language=en-US}}</ref> र यो संशोधन २०७२ फागुन १६ गतेदेखि लागू भएको थियो। यो संशोधन तराई-मधेस आन्दोलनकारी दलका मागहरूलाई आंशिक रूपमा सम्बोधन गर्न ल्याइएको थियो। == संशोधन == {| class="wikitable" |+ !क्रम !धारा !विद्यमान व्यवस्था<ref>{{Cite web |title=28. नेपालकाे संविधान |url=http://rajpatra.dop.gov.np/welcome/book/?ref=22517 |access-date=2026-06-11 |website=rajpatra.dop.gov.np}}</ref> !संशोधित व्यवस्था<ref>{{Cite web |title=नेपालको संविधान (पहिलो संशोधन), २०७२ |url=https://www.moljpa.gov.np/public/uploads/c2cb256b-c748-4fc3-8e5c-ef08b94f0560.pdf}}</ref> |- |१ |धारा ४२ को उपधारा (१) |सामाजिक रूपले पछाडि परेका महिला, दलित, आदिवासी जनजाति, मधेशी, थारू, मुस्लिम, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |आर्थिक, सामाजिक वा शैक्षिक दृष्टिले पछाडि परेका महिला दलित, आदिवासी जनजाति, मधेसी, थारू, मुस्लिम, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |- |२ |धारा ८४ को उपधारा (१) को खण्ड (क) |नेपाललाई भूगोल र जनसंख्याको आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी पहिलो हुने निर्वाचित हुने निर्वाचन  प्रणाली बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |नेपाललाई जनसंख्या र भौगोलिक  अनुकुलता तथा विशिष्टता आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी [[पहिलो हुने निर्वाचित हुने निर्वाचन प्रणाली|पहिलो हुने निर्वाचित हुने]] निर्वाचन  प्रणाली बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |- |३ | २८६ उपधारा (५) |निर्वाचन क्षेत्र निर्धारण आयोगले यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसंख्या र भूगोल लाई प्रतिनिधित्वको आधारा मानी त्यस्तो निर्वाचन क्षेत्राजएए भूगोल, जनसंख्या र सदस्य संख्या बीचको अनुपात यथासम्भव समान हुने गरी निर्धारण गर्नेछ । |निर्वाचन क्षेत्र निर्धारण आयोगबाट यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा धारा ८४ को उपधारा (१) को खण्ड (क) को अधीनमा रही प्रतिनिधित्वको लागी जनसंख्यालाई मुख्य र भूगोला लाई दोस्रो आधार मानी संघीय कानून बमोजिम प्रदेशमा निर्वाचन क्षेत्र निर्धारन गरिनेछ र प्रदेशभित्र रहेका प्रत्येक जिल्लामा कम्तीमा एक निर्वाचन क्षेत्र रहनेछन् । |- |४ |२८६ उपधारा (६) |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाईइ समेत ध्यान दिनु पर्नेछ। |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसङ्ख्या र भौगोलिक अनुकुलता, सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाईइ समेत ध्यान दिनु पर्नेछ । |} ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} lv9go6autuez0kldzlbpxqa7qo7m7k0 1361187 1361174 2026-06-12T04:27:40Z Bishaldev100 28807 /* संशोधन */ 1361187 wikitext text/x-wiki {{Infobox legislation |short_title = नेपालको संविधान पहिलो संशोधन, २०७७ |legislature = [[नेपालको सङ्घीय संसद|नेपालको संसद]] |image = |imagesize = 150px |imagealt = |caption = |long_title = |citation = [http://rajpatra.dop.gov.np/welcome/book/?ref=24111 दोस्रो संशोधन] |territorial_extent = [[नेपाल]] |enacted_by = [[प्रतिनिधि सभा (नेपाल)|प्रतिनिधि सभा]] |date_passed = ०९ माघ २०७२ |enacted_by2 = [[राष्ट्रिय सभा (नेपाल)|राष्ट्रिय सभा]] |date_passed2 = ०९ माघ २०७२ |date_assented = |signed_by = [[विद्यादेवी भण्डारी]] |date_commenced = २०७२ फागुन १६ |date_repealed = |administered_by = |bill = नेपालको संविधान पहिलो संशोधन विधेयक, २०७२ |bill_citation = |bill_date = |introduced_by =[[खड्गप्रसाद ओली|केपी शर्मा ओली]] |1st_reading = |2nd_reading = |3rd_reading = |conf_committee_passed = |bill2 = |bill_citation2 = |bill_date2 = |introduced_by2 = |1st_reading2 = |2nd_reading2 = |3rd_reading2 = |conf_committee_passed2 = |date_conf_committee = |white_paper = |committee_report = |amendments = |repeals = |related_legislation = |summary = |keywords = |status = सक्रिय }} {{ढाँचा:नेपालको संविधान २०७२}} नेपालको संविधानको पहिलो संशोधन, २०७२ लाई २०७२ साल माघ ९ गतेको व्यवस्थापिका-संसद्ले दुई तिहाइ बहुमतले पारित गरेको थियो<ref>{{Cite web |last=शर्मा |first=ओम |date=०९ माघ २०७२ |title=संविधानको पहिलो संशोधन विधेयक पारित, पक्षमा ४६१ र विपक्षमा सात मत |url=https://www.ratopati.com/story/293461 |access-date= |website=www.ratopati.com |language=Nepali}}</ref><ref>{{Cite web |title=मधेसी मोर्चाको माग आंशिक सम्वोधन गर्दै संविधानमा पहिलो संशोधन, पक्षमा ४६१, विपक्षमा ७ मत |url=https://www.onlinekhabar.com/2016/01/378773/%e0%a4%ae%e0%a4%a7%e0%a5%87%e0%a4%b8%e0%a5%80-%e0%a4%ae%e0%a5%8b%e0%a4%b0%e0%a5%8d%e0%a4%9a%e0%a4%be%e0%a4%95%e0%a5%8b-%e0%a4%ae%e0%a4%be%e0%a4%97-%e0%a4%86%e0%a4%82%e0%a4%b6%e0%a4%bf%e0%a4%95 |access-date=2026-06-11 |website=Online Khabar |language=en-US}}</ref> र यो संशोधन २०७२ फागुन १६ गतेदेखि लागू भएको थियो। यो संशोधन तराई-मधेस आन्दोलनकारी दलका मागहरूलाई आंशिक रूपमा सम्बोधन गर्न ल्याइएको थियो। == संशोधन == {| class="wikitable" |+ !क्रम !धारा !विद्यमान व्यवस्था<ref>{{Cite web |title=28. नेपालकाे संविधान |url=http://rajpatra.dop.gov.np/welcome/book/?ref=22517 |access-date=2026-06-11 |website=rajpatra.dop.gov.np}}</ref> !संशोधित व्यवस्था<ref>{{Cite web |title=नेपालको संविधान (पहिलो संशोधन), २०७२ |url=https://www.moljpa.gov.np/public/uploads/c2cb256b-c748-4fc3-8e5c-ef08b94f0560.pdf}}</ref> |- |१ |धारा ४२ को उपधारा (१) |सामाजिक रूपले पछाडि परेका महिला, दलित, आदिवासी जनजाति, मधेशी, थारू, मुस्लिम, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |आर्थिक, सामाजिक वा शैक्षिक दृष्टिले पछाडि परेका महिला दलित, आदिवासी जनजाति, मधेसी, थारू, मुस्लिम, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |- |२ |धारा ८४ को उपधारा (१) को खण्ड (क) |नेपाललाई भूगोल र जनसंख्याको आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी [[पहिलो हुने निर्वाचित हुने निर्वाचन प्रणाली]] बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |नेपाललाई जनसंख्या र भौगोलिक  अनुकुलता तथा विशिष्टता आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी [[पहिलो हुने निर्वाचित हुने निर्वाचन प्रणाली]] बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |- |३ | २८६ उपधारा (५) |निर्वाचन क्षेत्र निर्धारण आयोगले यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसंख्या र भूगोल लाई प्रतिनिधित्वको आधार मानी त्यस्तो निर्वाचन क्षेत्राजएए भूगोल, जनसंख्या र सदस्य संख्या बीचको अनुपात यथासम्भव समान हुने गरी निर्धारण गर्नेछ । |निर्वाचन क्षेत्र निर्धारण आयोगबाट यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा धारा ८४ को उपधारा (१) को खण्ड (क) को अधीनमा रही प्रतिनिधित्वको लागी जनसंख्यालाई मुख्य र भूगोला लाई दोस्रो आधार मानी संघीय कानून बमोजिम प्रदेशमा निर्वाचन क्षेत्र निर्धारन गरिनेछ र प्रदेशभित्र रहेका प्रत्येक जिल्लामा कम्तीमा एक निर्वाचन क्षेत्र रहनेछन् । |- |४ |२८६ उपधारा (६) |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाई समेत ध्यान दिनु पर्नेछ। |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसङ्ख्या र भौगोलिक अनुकुलता, सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाई समेत ध्यान दिनु पर्नेछ । |} ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} b6rox8y6ynm82xkjwp6c6qng6xx0lms 1361189 1361187 2026-06-12T05:03:05Z Bishaldev100 28807 1361189 wikitext text/x-wiki {{Infobox legislation |short_title = नेपालको संविधान पहिलो संशोधन, २०७७ |legislature = [[नेपालको सङ्घीय संसद|नेपालको संसद]] |image = |imagesize = 150px |imagealt = |caption = |long_title = |citation = [http://rajpatra.dop.gov.np/welcome/book/?ref=24111 दोस्रो संशोधन] |territorial_extent = [[नेपाल]] |enacted_by = [[प्रतिनिधि सभा (नेपाल)|प्रतिनिधि सभा]] |date_passed = ०९ माघ २०७२ |enacted_by2 = [[राष्ट्रिय सभा (नेपाल)|राष्ट्रिय सभा]] |date_passed2 = ०९ माघ २०७२ |date_assented = |signed_by = [[विद्यादेवी भण्डारी]] |date_commenced = २०७२ फागुन १६ |date_repealed = |administered_by = |bill = नेपालको संविधान पहिलो संशोधन विधेयक, २०७२ |bill_citation = |bill_date = |introduced_by =[[खड्गप्रसाद ओली|केपी शर्मा ओली]] |1st_reading = |2nd_reading = |3rd_reading = |conf_committee_passed = |bill2 = |bill_citation2 = |bill_date2 = |introduced_by2 = |1st_reading2 = |2nd_reading2 = |3rd_reading2 = |conf_committee_passed2 = |date_conf_committee = |white_paper = |committee_report = |amendments = |repeals = |related_legislation = |summary = |keywords = |status = सक्रिय }} {{ढाँचा:नेपालको संविधान २०७२}} [[नेपालको संविधान २०७२|नेपालको संविधान]]को पहिलो संशोधन तराई-मधेस आन्दोलनकारी दलका मागहरूलाई आंशिक रूपमा सम्बोधन गर्न ल्याइएको थियो। यो संशोधन प्रस्तावलाई २०७२ साल माघ ९ गतेको व्यवस्थापिका-संसद्ले दुई तिहाइ बहुमतले पारित गरेको थियो<ref>{{Cite web |last=शर्मा |first=ओम |date=०९ माघ २०७२ |title=संविधानको पहिलो संशोधन विधेयक पारित, पक्षमा ४६१ र विपक्षमा सात मत |url=https://www.ratopati.com/story/293461 |access-date= |website=www.ratopati.com |language=Nepali}}</ref><ref>{{Cite web |title=मधेसी मोर्चाको माग आंशिक सम्वोधन गर्दै संविधानमा पहिलो संशोधन, पक्षमा ४६१, विपक्षमा ७ मत |url=https://www.onlinekhabar.com/2016/01/378773/%e0%a4%ae%e0%a4%a7%e0%a5%87%e0%a4%b8%e0%a5%80-%e0%a4%ae%e0%a5%8b%e0%a4%b0%e0%a5%8d%e0%a4%9a%e0%a4%be%e0%a4%95%e0%a5%8b-%e0%a4%ae%e0%a4%be%e0%a4%97-%e0%a4%86%e0%a4%82%e0%a4%b6%e0%a4%bf%e0%a4%95 |access-date=2026-06-11 |website=Online Khabar |language=en-US}}</ref> र यो संशोधन २०७२ फागुन १६ गतेदेखि लागू भएको थियो। == पृष्ठभूमी == == संशोधन == {| class="wikitable" |+ !क्रम !धारा !विद्यमान व्यवस्था<ref>{{Cite web |title=28. नेपालकाे संविधान |url=http://rajpatra.dop.gov.np/welcome/book/?ref=22517 |access-date=2026-06-11 |website=rajpatra.dop.gov.np}}</ref> !संशोधित व्यवस्था<ref>{{Cite web |title=नेपालको संविधान (पहिलो संशोधन), २०७२ |url=https://www.moljpa.gov.np/public/uploads/c2cb256b-c748-4fc3-8e5c-ef08b94f0560.pdf}}</ref> |- |१ |धारा ४२ को उपधारा (१) |सामाजिक रूपले पछाडि परेका महिला, दलित, आदिवासी जनजाति, मधेशी, थारू, मुस्लिम, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |आर्थिक, सामाजिक वा शैक्षिक दृष्टिले पछाडि परेका महिला दलित, आदिवासी जनजाति, मधेसी, थारू, मुस्लिम, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |- |२ |धारा ८४ को उपधारा (१) को खण्ड (क) |नेपाललाई भूगोल र जनसंख्याको आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी [[पहिलो हुने निर्वाचित हुने निर्वाचन प्रणाली]] बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |नेपाललाई जनसंख्या र भौगोलिक  अनुकुलता तथा विशिष्टता आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी [[पहिलो हुने निर्वाचित हुने निर्वाचन प्रणाली]] बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |- |३ | २८६ उपधारा (५) |निर्वाचन क्षेत्र निर्धारण आयोगले यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसंख्या र भूगोल लाई प्रतिनिधित्वको आधार मानी त्यस्तो निर्वाचन क्षेत्राजएए भूगोल, जनसंख्या र सदस्य संख्या बीचको अनुपात यथासम्भव समान हुने गरी निर्धारण गर्नेछ । |निर्वाचन क्षेत्र निर्धारण आयोगबाट यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा धारा ८४ को उपधारा (१) को खण्ड (क) को अधीनमा रही प्रतिनिधित्वको लागी जनसंख्यालाई मुख्य र भूगोला लाई दोस्रो आधार मानी संघीय कानून बमोजिम प्रदेशमा निर्वाचन क्षेत्र निर्धारन गरिनेछ र प्रदेशभित्र रहेका प्रत्येक जिल्लामा कम्तीमा एक निर्वाचन क्षेत्र रहनेछन् । |- |४ |२८६ उपधारा (६) |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाई समेत ध्यान दिनु पर्नेछ। |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसङ्ख्या र भौगोलिक अनुकुलता, सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाई समेत ध्यान दिनु पर्नेछ । |} ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} 6i29420yidfftm1xh6fd0ngd6dwm3zv 1361190 1361189 2026-06-12T05:08:39Z Bishaldev100 28807 /* पृष्ठभूमी */ 1361190 wikitext text/x-wiki {{Infobox legislation |short_title = नेपालको संविधान पहिलो संशोधन, २०७७ |legislature = [[नेपालको सङ्घीय संसद|नेपालको संसद]] |image = |imagesize = 150px |imagealt = |caption = |long_title = |citation = [http://rajpatra.dop.gov.np/welcome/book/?ref=24111 दोस्रो संशोधन] |territorial_extent = [[नेपाल]] |enacted_by = [[प्रतिनिधि सभा (नेपाल)|प्रतिनिधि सभा]] |date_passed = ०९ माघ २०७२ |enacted_by2 = [[राष्ट्रिय सभा (नेपाल)|राष्ट्रिय सभा]] |date_passed2 = ०९ माघ २०७२ |date_assented = |signed_by = [[विद्यादेवी भण्डारी]] |date_commenced = २०७२ फागुन १६ |date_repealed = |administered_by = |bill = नेपालको संविधान पहिलो संशोधन विधेयक, २०७२ |bill_citation = |bill_date = |introduced_by =[[खड्गप्रसाद ओली|केपी शर्मा ओली]] |1st_reading = |2nd_reading = |3rd_reading = |conf_committee_passed = |bill2 = |bill_citation2 = |bill_date2 = |introduced_by2 = |1st_reading2 = |2nd_reading2 = |3rd_reading2 = |conf_committee_passed2 = |date_conf_committee = |white_paper = |committee_report = |amendments = |repeals = |related_legislation = |summary = |keywords = |status = सक्रिय }} {{ढाँचा:नेपालको संविधान २०७२}} [[नेपालको संविधान २०७२|नेपालको संविधान]]को पहिलो संशोधन तराई-मधेस आन्दोलनकारी दलका मागहरूलाई आंशिक रूपमा सम्बोधन गर्न ल्याइएको थियो। यो संशोधन प्रस्तावलाई २०७२ साल माघ ९ गतेको व्यवस्थापिका-संसद्ले दुई तिहाइ बहुमतले पारित गरेको थियो<ref>{{Cite web |last=शर्मा |first=ओम |date=०९ माघ २०७२ |title=संविधानको पहिलो संशोधन विधेयक पारित, पक्षमा ४६१ र विपक्षमा सात मत |url=https://www.ratopati.com/story/293461 |access-date= |website=www.ratopati.com |language=Nepali}}</ref><ref>{{Cite web |title=मधेसी मोर्चाको माग आंशिक सम्वोधन गर्दै संविधानमा पहिलो संशोधन, पक्षमा ४६१, विपक्षमा ७ मत |url=https://www.onlinekhabar.com/2016/01/378773/%e0%a4%ae%e0%a4%a7%e0%a5%87%e0%a4%b8%e0%a5%80-%e0%a4%ae%e0%a5%8b%e0%a4%b0%e0%a5%8d%e0%a4%9a%e0%a4%be%e0%a4%95%e0%a5%8b-%e0%a4%ae%e0%a4%be%e0%a4%97-%e0%a4%86%e0%a4%82%e0%a4%b6%e0%a4%bf%e0%a4%95 |access-date=2026-06-11 |website=Online Khabar |language=en-US}}</ref> र यो संशोधन २०७२ फागुन १६ गतेदेखि लागू भएको थियो। == पृष्ठभूमी == नेपालको संविधान २०७२ असोज १ गते संविधानसभाका बहुमत सदस्यहरूबाट हस्ताक्षर भएपछि सभाध्यक्षबाट प्रमाणित गरिएको थियो। २०७२ असोज ३ गते राष्ट्रपति रामवरण यादवले नेपालको संविधान २०७२ मा हस्ताक्षर गर्दै संविधान जारी भएको घोषणा गरेपछी तराईको जिल्लाहरूमा "असोज तीन, कालोदिन" भनि विरोध भइरहेको थियो । विसं २०७२ आश्विन ०६ गतेबाट नेपालले जारी गरेको [[नेपालको संविधान २०७२|नेपालको संबिधान, २०७२]] प्रति असन्तुष्टि जनाउँदै भारतले [[२०७२ नेपाल नाकाबन्दी|आर्थिक नाकाबन्दी]] लगायो। == संशोधन == {| class="wikitable" |+ !क्रम !धारा !विद्यमान व्यवस्था<ref>{{Cite web |title=28. नेपालकाे संविधान |url=http://rajpatra.dop.gov.np/welcome/book/?ref=22517 |access-date=2026-06-11 |website=rajpatra.dop.gov.np}}</ref> !संशोधित व्यवस्था<ref>{{Cite web |title=नेपालको संविधान (पहिलो संशोधन), २०७२ |url=https://www.moljpa.gov.np/public/uploads/c2cb256b-c748-4fc3-8e5c-ef08b94f0560.pdf}}</ref> |- |१ |धारा ४२ को उपधारा (१) |सामाजिक रूपले पछाडि परेका महिला, दलित, आदिवासी जनजाति, मधेशी, थारू, मुस्लिम, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |आर्थिक, सामाजिक वा शैक्षिक दृष्टिले पछाडि परेका महिला दलित, आदिवासी जनजाति, मधेसी, थारू, मुस्लिम, पिछडावर्ग, अल्पसङ्ख्यक, सीमान्तकृत, अपाङ्गता भएका व्यक्ति, लैंँङ्गिक तथा यौनिक अल्पसंख्यक, किसान, श्रमिक, उत्पीडित वा पिछडिएको क्षेत्रका नागरिक तथा आर्थिक रूपले विपन्न खस आर्यलाई समानुपातिक समावेशी सिद्धान्तका आधारमा राज्यको निकायमा सहभागिताको हक हुनेछ । |- |२ |धारा ८४ को उपधारा (१) को खण्ड (क) |नेपाललाई भूगोल र जनसंख्याको आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी [[पहिलो हुने निर्वाचित हुने निर्वाचन प्रणाली]] बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |नेपाललाई जनसंख्या र भौगोलिक  अनुकुलता तथा विशिष्टता आधारमा एक सय पैंसठ्ठी निर्वाचन क्षेत्र कायम गरी प्रत्येक निर्वाचन क्षेत्रबाट एक जना रहने गरी [[पहिलो हुने निर्वाचित हुने निर्वाचन प्रणाली]] बमोजिम निर्वाचित हुने एक सय पैंसठ्ठी सदस्य |- |३ | २८६ उपधारा (५) |निर्वाचन क्षेत्र निर्धारण आयोगले यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसंख्या र भूगोल लाई प्रतिनिधित्वको आधार मानी त्यस्तो निर्वाचन क्षेत्राजएए भूगोल, जनसंख्या र सदस्य संख्या बीचको अनुपात यथासम्भव समान हुने गरी निर्धारण गर्नेछ । |निर्वाचन क्षेत्र निर्धारण आयोगबाट यस धारा बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा धारा ८४ को उपधारा (१) को खण्ड (क) को अधीनमा रही प्रतिनिधित्वको लागी जनसंख्यालाई मुख्य र भूगोला लाई दोस्रो आधार मानी संघीय कानून बमोजिम प्रदेशमा निर्वाचन क्षेत्र निर्धारन गरिनेछ र प्रदेशभित्र रहेका प्रत्येक जिल्लामा कम्तीमा एक निर्वाचन क्षेत्र रहनेछन् । |- |४ |२८६ उपधारा (६) |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाई समेत ध्यान दिनु पर्नेछ। |उपधारा (५) बमोजिम निर्वाचन क्षेत्र निर्धारण गर्दा जनसङ्ख्या र भौगोलिक अनुकुलता, सो क्षेत्रको जनसंख्याको घनत्व, भौगोलिक विशिष्टता, प्रशासनिक एवं यातायातको सुगमता, सामुदायिक तथा सांस्कृतिक पक्षलाई समेत ध्यान दिनु पर्नेछ । |} ==सन्दर्भ सामग्रीहरू== {{सन्दर्भसूची}} 4egymhgu2lvcqtfvrxunmp2hvm2hhsz प्रयोगकर्ता वार्ता:Aayush Dhital 3 150520 1361179 2026-06-12T01:52:52Z नेपाली विकिपिडिया स्वागत 28168 [[Template:Welcome|स्वागतम्]] 1361179 wikitext text/x-wiki ==विकिपिडियामा स्वागत छ!== <div style="width: 99%; color: #111; {{box-shadow|0|1px|3px|rgba(0, 0, 0, 0.35)}} {{border-radius|2px}}"> <div style="overflow:hidden; height:auto; background: #fff; width: 100%; padding-bottom:18px;"> <div style="font-size: 36px; margin-top: 24px;margin-left: 16px; font-family: 'Linux Libertine',Georgia,Times,serif; line-height: 1.2em;">नमस्ते, Aayush Dhitalज्यू</div> <div style="font-size: 24px; padding-top: 0px; margin-left: 16px; font-family: 'Linux Libertine',Georgia,Times,serif; line-height:1.2em; color: #666; "> [[नेपाली विकिपिडिया]]मा हार्दिक [[विकिपिडिया:स्वागत|स्वागत]] छ! </div></div> <div style="vertical-align:middle; color: black; background-color:#fff"> <div style="display: flex; flex-flow: row wrap; background-color:#EAECF0; padding: 10px; padding-left: 25px; "> <div style="font-size: 18px; padding-top: 0px; margin-left: 0px; text-align: center; font-family: 'Linux Libertine',Georgia,Times,serif; line-height:1.5em; color: #111; "> हालसम्म नेपाली विकिपिडियामा [[विशेष:Statistics|२९,८२३]] लेखहरू छन्। यसलाई बढाउन तपाईंको योगदानको आवश्यकता रहेको छ। आउनुहोस् तपाईं हामी सबै मिलेर नेपाली विकिपिडियालाई विश्वका अन्य प्रमुख [[:meta:List_of_Wikipedias/ne|भाषाका विकिपिडिया जत्ति कै धनी]] बनाऔँ। विकिपिडियाले कुनै पनि व्यक्तिलाई सम्पादन गर्ने अधिकार दिन्छ। मलाई आशा छ कि तपाईंले यहाँ मन पराउनुहुन्छ र योगदान गर्ने निर्णय गर्नुहुन्छ।</div> <div style="flex: 1 1 300px;"><br/> <div style="font-size: 17px; font-family: 'Linux Libertine',Georgia,Times,serif; line-height:1.2em; font-weight:normal;">[[चित्र:Symbol support2 vote.svg|25px|alt=|link=]] सुरुवात</div> <div style="font-size: 15px;"> * पहिले [[विकिपिडिया:विकिपिडियाको बारेमा|विकिपिडियाको परिचय पृष्ठ]] पढ्नुहोस्। * तपाईंले कसरी [[मद्दत:सहायता विषयसूचि|विकिपिडियामा योगदान गर्न सक्नुहुन्छ]] जान्नुहोस्। * आफ्नो परिचय दिनको लागि तपाईंको [[प्रयोगकर्ता:Aayush Dhital|प्रयोगकर्ता पृष्ठ]] बनाउनुहोला ताकि हामी तपाईंलाई अझ राम्रोसँग चिन्न सक्छौँ। (परिचय दिइरहनु आवश्यक नै भने छैन) </div> </div> <div style="flex: 1 1 300px;"><br/> <div style="font-size: 17px; font-family: 'Linux Libertine',Georgia,Times,serif; line-height:1.2em; font-weight:normal;">[[चित्र:Artículo bueno-blue.svg|25px|alt=|link=]] सुझावहरू</div> <div style="font-size: 15px;"> * कृपया [[विकिपिडिया:स्वशिक्षा/वार्तालाप पृष्ठ|वार्तालाप पृष्ठ]]मा चारवटा वक्र (<code><nowiki>~~~~</nowiki></code>) प्रयोग गरि हस्ताक्षर गर्नुहोला। यसो गर्नाले वार्तालाप पृष्ठमा स्वत: तपाईंको नाम, वार्ता पृष्ठसूत्र र मिति थपिने छ। * यदि तपाईंलाई विकिपिडियामा केही समस्या परेको छ भने आफ्नो वार्तालाप पृष्ठमा <code>'''<nowiki>{{मद्दत}}</nowiki>'''</code> राख्नु होला। हाम्रा प्रयोगकर्ताहरूले तपाईंको समस्याको समाधान बताउने छन्। * नयाँ पृष्ठहरू [[विकिपिडिया:स्वशिक्षा/सम्पादन|सम्पादन गर्दा]] वा [[विकिपिडिया:कसरी लेख बनाउने?|सिर्जना गर्दा]], [[विकिपिडिया:स्वशिक्षा/सन्दर्भ|सन्दर्भ]]हरू थप्दा वा मेटाउँदा गल्ती गर्न डराउनु पर्दैन किनकि गल्ती जो कोहीबाट हुन् सक्छ। </div> </div> </div> <div style="padding: 10px; padding-left: 25px; "> <div style="text-align: center;"> {{clickable button 2|विकिपिडिया:कसरी लेख बनाउने?|कसरी लेख बनाउने?|class=mw-ui-constructive center}} </div> <div style="text-align: center;"> {{clickable button 2|विकिपिडिया:चिया घर|यदि तपाईंसँग प्रश्नहरू छन् भने यहाँ सोध्नुहोस्|class=mw-ui-constructive center}} </div> </div> </div> </div> '''स्वागतम्''', हामी नेपाली विकिपिडियामा तपाईंको सम्पादनको लागि पर्खिरहेका छौँ! -- [[User:नेपाली विकिपिडिया स्वागत|नेपाली विकिपिडिया स्वागत]] ([[User talk:नेपाली विकिपिडिया स्वागत|कुरा गर्नुहोस्]]) ०७:३७, १२ जुन २०२६ (नेपाली समय) 3k47x5m5tk90do814qvzf0uvx9mn7c4 प्रचलित लिपि 0 150521 1361182 2026-06-12T01:56:26Z Jujubhaju 67302 Jujubhajuद्वारा [[प्रचलित लिपि]] पृष्ठलाई [[नेवारी लिपि]]मा सारियो: प्रचलित शीर्षक 1361182 wikitext text/x-wiki #अनुप्रेषण [[नेवारी लिपि]] rpjd822t4of2nw5p2d9rxe4k1voizn2 प्रयोगकर्ता वार्ता:सुरेश कुमार मल्ल 3 150522 1361196 2026-06-12T05:57:33Z नेपाली विकिपिडिया स्वागत 28168 [[ढाँचा:नमस्ते|स्वागतम्]] 1361196 wikitext text/x-wiki ==विकिपिडियामा स्वागत छ!== <div style="width: 99%; color: #111; {{box-shadow|0|1px|3px|rgba(0, 0, 0, 0.35)}} {{border-radius|2px}}"> <div style="overflow:hidden; height:auto; background: #fff; width: 100%; padding-bottom:18px;"> <div style="font-size: 36px; margin-top: 24px;margin-left: 16px; font-family: 'Linux Libertine',Georgia,Times,serif; line-height: 1.2em;">नमस्ते, सुरेश कुमार मल्लज्यू</div> <div style="font-size: 24px; padding-top: 0px; margin-left: 16px; font-family: 'Linux Libertine',Georgia,Times,serif; line-height:1.2em; color: #666; "> [[नेपाली विकिपिडिया]]मा हार्दिक [[विकिपिडिया:स्वागत|स्वागत]] छ! </div></div> <div style="vertical-align:middle; color: black; background-color:#fff"> <div style="display: flex; flex-flow: row wrap; background-color:#EAECF0; padding: 10px; padding-left: 25px; "> <div style="font-size: 18px; padding-top: 0px; margin-left: 0px; text-align: center; font-family: 'Linux Libertine',Georgia,Times,serif; line-height:1.5em; color: #111; "> हालसम्म नेपाली विकिपिडियामा [[विशेष:Statistics|२९,८२३]] लेखहरू छन्। यसलाई बढाउन तपाईंको योगदानको आवश्यकता रहेको छ। आउनुहोस् तपाईं हामी सबै मिलेर नेपाली विकिपिडियालाई विश्वका अन्य प्रमुख [[:meta:List_of_Wikipedias/ne|भाषाका विकिपिडिया जत्ति कै धनी]] बनाऔँ। विकिपिडियाले कुनै पनि व्यक्तिलाई सम्पादन गर्ने अधिकार दिन्छ। मलाई आशा छ कि तपाईंले यहाँ मन पराउनुहुन्छ र योगदान गर्ने निर्णय गर्नुहुन्छ।</div> <div style="flex: 1 1 300px;"><br/> <div style="font-size: 17px; font-family: 'Linux Libertine',Georgia,Times,serif; line-height:1.2em; font-weight:normal;">[[चित्र:Symbol support2 vote.svg|25px|alt=|link=]] सुरुवात</div> <div style="font-size: 15px;"> * पहिले [[विकिपिडिया:विकिपिडियाको बारेमा|विकिपिडियाको परिचय पृष्ठ]] पढ्नुहोस्। * तपाईंले कसरी [[मद्दत:सहायता विषयसूचि|विकिपिडियामा योगदान गर्न सक्नुहुन्छ]] जान्नुहोस्। * आफ्नो परिचय दिनको लागि तपाईंको [[प्रयोगकर्ता:सुरेश कुमार मल्ल|प्रयोगकर्ता पृष्ठ]] बनाउनुहोला ताकि हामी तपाईंलाई अझ राम्रोसँग चिन्न सक्छौँ। (परिचय दिइरहनु आवश्यक नै भने छैन) </div> </div> <div style="flex: 1 1 300px;"><br/> <div style="font-size: 17px; font-family: 'Linux Libertine',Georgia,Times,serif; line-height:1.2em; font-weight:normal;">[[चित्र:Artículo bueno-blue.svg|25px|alt=|link=]] सुझावहरू</div> <div style="font-size: 15px;"> * कृपया [[विकिपिडिया:स्वशिक्षा/वार्तालाप पृष्ठ|वार्तालाप पृष्ठ]]मा चारवटा वक्र (<code><nowiki>~~~~</nowiki></code>) प्रयोग गरि हस्ताक्षर गर्नुहोला। यसो गर्नाले वार्तालाप पृष्ठमा स्वत: तपाईंको नाम, वार्ता पृष्ठसूत्र र मिति थपिने छ। * यदि तपाईंलाई विकिपिडियामा केही समस्या परेको छ भने आफ्नो वार्तालाप पृष्ठमा <code>'''<nowiki>{{मद्दत}}</nowiki>'''</code> राख्नु होला। हाम्रा प्रयोगकर्ताहरूले तपाईंको समस्याको समाधान बताउने छन्। * नयाँ पृष्ठहरू [[विकिपिडिया:स्वशिक्षा/सम्पादन|सम्पादन गर्दा]] वा [[विकिपिडिया:कसरी लेख बनाउने?|सिर्जना गर्दा]], [[विकिपिडिया:स्वशिक्षा/सन्दर्भ|सन्दर्भ]]हरू थप्दा वा मेटाउँदा गल्ती गर्न डराउनु पर्दैन किनकि गल्ती जो कोहीबाट हुन् सक्छ। </div> </div> </div> <div style="padding: 10px; padding-left: 25px; "> <div style="text-align: center;"> {{clickable button 2|विकिपिडिया:कसरी लेख बनाउने?|कसरी लेख बनाउने?|class=mw-ui-constructive center}} </div> <div style="text-align: center;"> {{clickable button 2|विकिपिडिया:चिया घर|यदि तपाईंसँग प्रश्नहरू छन् भने यहाँ सोध्नुहोस्|class=mw-ui-constructive center}} </div> </div> </div> </div> '''स्वागतम्''', हामी नेपाली विकिपिडियामा तपाईंको सम्पादनको लागि पर्खिरहेका छौँ! -- [[User:नेपाली विकिपिडिया स्वागत|नेपाली विकिपिडिया स्वागत]] ([[User talk:नेपाली विकिपिडिया स्वागत|कुरा गर्नुहोस्]]) ११:४२, १२ जुन २०२६ (नेपाली समय) nfo9p3l9jsp6ybt3jifuwwd2qz0p7q1 मोड्युल:Goalscorers 828 150523 1361204 2018-12-13T09:19:41Z en>Jts1882 0 create and return simple message to [[Template:goalscorers/sandbox]] 1361204 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" local data = {} --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end function p.main(frame) return ("no goals to report") end return p 8ydh39y2rkpxur31knspfqztbluzj19 1361205 1361204 2018-12-13T10:07:45Z en>Jts1882 0 output the goalscorers in simple form 1361205 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) local outputString = "" local goalscorers = data.goalscorers for k,v in pairs(goalscorers) do local scorerString = "\n* " .. v[1] .. " (" .. v[2] .. ") " -- name (country) .. tostring(v[4]+v[5]) .. " goals" -- total goals outputString = outputString .. scorerString end if outputString ~= "" then return outputString else return ("no goals to report") end end return p c7fdu7elj15squ3jfdv4r283eon0nw4 1361206 1361205 2018-12-13T15:31:00Z en>Jts1882 0 output list of all players with all goals 1361206 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) local outputString = "" local goalscorers = data.goalscorers local unsortedTable = {} -- select all players with goals totals for appropriate rounds local goals = 0 local group = "" for k,v in pairs(goalscorers) do if group ~= "" then -- group stage only if v[3] == group then goals = v[4] unsortedTable[#unsortedTable+1] = {name=v[1], country=v[2], goals=goals } end else -- all players and goals goals = v[4] + v[5] -- total goals (TODO add option ) -- player, country, group, total goals unsortedTable[#unsortedTable+1] = { v[1], v[2], goals } end end -- sort by goals table.sort( unsortedTable, function( a, b ) return a[3] > b[3] end ) local goalNumber = 1000 for j,u in pairs(unsortedTable) do if u[3] < goalNumber then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } outputString = outputString .. "\n'''" .. u[3] .. " goals'''\n" outputString = outputString .. frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } goalNumber = u[3] end local scorerString = "\n*" -- wikitext list .. frame:expandTemplate{ title = 'flagicon', args = { u[2] } } -- flagicon .. " [[" .. u[1] .. "]]" -- name outputString = outputString .. scorerString -- .. " " .. tostring(u[4]) end if outputString ~= "" then return outputString else return ("no goals to report") end end --[[ sort function from https://stackoverflow.com/questions/15706270/sort-a-table-in-lua ]] function p.sortTable(unsortedTable) local sortedTable = {} for k,v in p.spairs(unsortedTable, function(t,a,b) return t[b] < t[a] end) do sortedTable[k] = v end return sortedTable end function p.spairs(t, order) -- collect the keys local keys = {} for k in pairs(t) do keys[#keys+1] = k end -- if order function given, sort by it by passing the table and keys a, b, -- otherwise just sort the keys if order then table.sort(keys, function(a,b) return order(t, a, b) end) else table.sort(keys) --table.sort(keys, function(a,b) return t[b] < t[a] end) -- this works for fixed sort end -- return the iterator function local i = 0 return function() i = i + 1 if keys[i] then return keys[i], t[keys[i]] end end end return p h9jlu73qdkbiplr114ysmsxow69m15a 1361207 1361206 2018-12-13T16:03:55Z en>Jts1882 0 add options for round and group 1361207 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "" -- group = all(empty), A,B,C etc (could be numbers as string) for k,v in pairs(data.goalscorers) do local goals = 0 if round == "group" then -- group round only if group == v[3] then -- single group only goals = v[4] elseif group == "" then -- any group goals = v[4] end elseif round == "playoffs" then -- playoff round goals = v[5] else -- all rounds and goals goals = v[4] + v[5] end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort by goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) local goalNumber = 1000 for j,u in pairs(goalscorers) do if u['goals'] < goalNumber then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" outputString = outputString .. frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } goalNumber = u['goals'] end local scorerString = "\n*" -- wikitext list .. frame:expandTemplate{ title = 'flagicon', args = { u['country'] } } -- flagicon .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. scorerString -- .. " " .. tostring(u['goals']) end if outputString ~= "" then return outputString else return ("no goals to report") end end --[[ sort function from https://stackoverflow.com/questions/15706270/sort-a-table-in-lua ]] function p.sortTable(unsortedTable) local sortedTable = {} for k,v in p.spairs(unsortedTable, function(t,a,b) return t[b] < t[a] end) do sortedTable[k] = v end return sortedTable end function p.spairs(t, order) -- collect the keys local keys = {} for k in pairs(t) do keys[#keys+1] = k end -- if order function given, sort by it by passing the table and keys a, b, -- otherwise just sort the keys if order then table.sort(keys, function(a,b) return order(t, a, b) end) else table.sort(keys) --table.sort(keys, function(a,b) return t[b] < t[a] end) -- this works for fixed sort end -- return the iterator function local i = 0 return function() i = i + 1 if keys[i] then return keys[i], t[keys[i]] end end end return p g97udap9ur35x6medqjvs5m8kzehem6 1361208 1361207 2018-12-13T16:08:40Z en>Jts1882 0 get args 1361208 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "" -- group = all(empty), A,B,C etc (could be numbers as string) for k,v in pairs(data.goalscorers) do local goals = 0 if round == "group" then -- group round only if group == v[3] then -- single group only goals = v[4] elseif group == "" then -- any group goals = v[4] end elseif round == "playoffs" then -- playoff round goals = v[5] else -- all rounds and goals goals = v[4] + v[5] end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort by goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) local goalNumber = 1000 for j,u in pairs(goalscorers) do if u['goals'] < goalNumber then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" outputString = outputString .. frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } goalNumber = u['goals'] end local scorerString = "\n*" -- wikitext list .. frame:expandTemplate{ title = 'flagicon', args = { u['country'] } } -- flagicon .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. scorerString -- .. " " .. tostring(u['goals']) end if outputString ~= "" then return outputString else return ("no goals to report") end end --[[ sort function from https://stackoverflow.com/questions/15706270/sort-a-table-in-lua ]] function p.sortTable(unsortedTable) local sortedTable = {} for k,v in p.spairs(unsortedTable, function(t,a,b) return t[b] < t[a] end) do sortedTable[k] = v end return sortedTable end function p.spairs(t, order) -- collect the keys local keys = {} for k in pairs(t) do keys[#keys+1] = k end -- if order function given, sort by it by passing the table and keys a, b, -- otherwise just sort the keys if order then table.sort(keys, function(a,b) return order(t, a, b) end) else table.sort(keys) --table.sort(keys, function(a,b) return t[b] < t[a] end) -- this works for fixed sort end -- return the iterator function local i = 0 return function() i = i + 1 if keys[i] then return keys[i], t[keys[i]] end end end return p 9wrnsluhukd1oo4lfef5u0rj4u0yla5 1361209 1361208 2018-12-13T16:11:19Z en>Jts1882 0 remove the stackoverflow sort function 1361209 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "" -- group = all(empty), A,B,C etc (could be numbers as string) for k,v in pairs(data.goalscorers) do local goals = 0 if round == "group" then -- group round only if group == v[3] then -- single group only goals = v[4] elseif group == "" then -- any group goals = v[4] end elseif round == "playoffs" then -- playoff round goals = v[5] else -- all rounds and goals goals = v[4] + v[5] end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort by goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) local goalNumber = 1000 for j,u in pairs(goalscorers) do if u['goals'] < goalNumber then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" outputString = outputString .. frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } goalNumber = u['goals'] end local scorerString = "\n*" -- wikitext list .. frame:expandTemplate{ title = 'flagicon', args = { u['country'] } } -- flagicon .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. scorerString -- .. " " .. tostring(u['goals']) outputString = outputString ..frame:expandTemplate{ title = 'div col end' } end if outputString ~= "" then return outputString else return ("no goals to report") end end return p as2tdp0hjmmun52m8v828m2fxa316ch 1361210 1361209 2018-12-13T16:14:08Z en>Jts1882 0 close the multicolumn list at end 1361210 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "" -- group = all(empty), A,B,C etc (could be numbers as string) for k,v in pairs(data.goalscorers) do local goals = 0 if round == "group" then -- group round only if group == v[3] then -- single group only goals = v[4] elseif group == "" then -- any group goals = v[4] end elseif round == "playoffs" then -- playoff round goals = v[5] else -- all rounds and goals goals = v[4] + v[5] end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort by goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) local goalNumber = 1000 for j,u in pairs(goalscorers) do if u['goals'] < goalNumber then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" outputString = outputString .. frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } goalNumber = u['goals'] end local scorerString = "\n*" -- wikitext list .. frame:expandTemplate{ title = 'flagicon', args = { u['country'] } } -- flagicon .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. scorerString -- .. " " .. tostring(u['goals']) end if outputString ~= "" then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } return outputString else return ("no goals to report") end end return p l4n1mxiwb5ekpj6mha27tgbtozzu8ot 1361211 1361210 2018-12-13T17:26:25Z en>S.A. Julio 0 testing column output, using {{fbicon}} for flags 1361211 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "" -- group = all(empty), A,B,C etc (could be numbers as string) for k,v in pairs(data.goalscorers) do local goals = 0 if round == "group" then -- group round only if group == v[3] then -- single group only goals = v[4] elseif group == "" then -- any group goals = v[4] end elseif round == "playoffs" then -- playoff round goals = v[5] else -- all rounds and goals goals = v[4] + v[5] end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort by goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) local goalNumber = 1000 for j,u in pairs(goalscorers) do if u['goals'] < goalNumber then outputString = outputString .. "<div class=\"div-col columns column-count column-count-3\" style=\"" .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. "\">" outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" outputString = outputString .. "</div>" goalNumber = u['goals'] end local scorerString = "\n*" -- wikitext list .. frame:expandTemplate{ title = 'fbicon', args = { u['country'] } } -- fbicon .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. scorerString -- .. " " .. tostring(u['goals']) end if outputString ~= "" then outputString = outputString ..frame:expandTemplate{ title = '</div>' } return outputString else return ("no goals to report") end end return p aljo4cr87dzxjy7einphq5rwvnz8gf8 1361212 1361211 2018-12-13T17:27:22Z en>S.A. Julio 0 restore 1361212 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "" -- group = all(empty), A,B,C etc (could be numbers as string) for k,v in pairs(data.goalscorers) do local goals = 0 if round == "group" then -- group round only if group == v[3] then -- single group only goals = v[4] elseif group == "" then -- any group goals = v[4] end elseif round == "playoffs" then -- playoff round goals = v[5] else -- all rounds and goals goals = v[4] + v[5] end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort by goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) local goalNumber = 1000 for j,u in pairs(goalscorers) do if u['goals'] < goalNumber then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" outputString = outputString .. frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } goalNumber = u['goals'] end local scorerString = "\n*" -- wikitext list .. frame:expandTemplate{ title = 'fbicon', args = { u['country'] } } -- fbicon .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. scorerString -- .. " " .. tostring(u['goals']) end if outputString ~= "" then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } return outputString else return ("no goals to report") end end return p 6upy7mgf03ivke8jwvmlipueewyifnt 1361213 1361212 2018-12-13T17:50:19Z en>Jts1882 0 add round handling 1361213 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort by goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) local goalNumber = 1000 for j,u in pairs(goalscorers) do if u['goals'] < goalNumber then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" outputString = outputString .. frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } goalNumber = u['goals'] end local scorerString = "\n*" -- wikitext list .. frame:expandTemplate{ title = 'fbicon', args = { u['country'] } } -- fbicon .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. scorerString -- .. " " .. tostring(u['goals']) end if outputString ~= "" then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } return outputString else return ("no goals to report") end end return p ixkoprko82u6ywel056vjej6fv1qmdb 1361214 1361213 2018-12-14T08:16:21Z en>Jts1882 0 use flag icon set in data module for tournament 1361214 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort by goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) local goalNumber = 1000 for j,u in pairs(goalscorers) do if u['goals'] < goalNumber then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" outputString = outputString .. frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } goalNumber = u['goals'] end local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local scorerString = "\n*" -- wikitext list .. frame:expandTemplate{ title = icon , args = { u['country'] } } -- flag icon .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. scorerString -- .. " " .. tostring(u['goals']) end if outputString ~= "" then outputString = outputString ..frame:expandTemplate{ title = 'div col end' } return outputString else return ("no goals to report") end end return p nvueqpyfvuqz0h2rbrs48sk3sykcowz 1361215 1361214 2018-12-14T08:45:11Z en>Jts1882 0 remove flag icon, start list and close list to functions, each calling desired template 1361215 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("no goals to report") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- wikitext list return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } end function p.closeList(frame) return frame:expandTemplate{ title = 'div col end' } end return p sxlih1ro3nvd8n1i8w20qqcykcrxkcr 1361216 1361215 2018-12-14T08:57:32Z en>Jts1882 0 add code for alternative 1361216 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("no goals to report") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- wikitext list return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) -- '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' return frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } end function p.closeList(frame) -- '</div>'' return frame:expandTemplate{ title = 'div col end' } end return p 7r964fzuffpbe2odxc1qmm3fas29fzq 1361217 1361216 2018-12-14T09:23:40Z en>Jts1882 0 test alternative formating of columns with <div> rather than template; leave latter in place 1361217 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("no goals to report") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) -- equivalent to {{Div col|colwidth=18em}} return frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } --return '<div class="div-col columns column-count column-count-3" style="' -- .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) -- equivalent to {{Div col end}} return frame:expandTemplate{ title = 'div col end' } --return '</div>' end return p k6i5oz8iz93z2ibeo4g2w9b2dtzgq9h 1361218 1361217 2018-12-14T09:29:41Z en>Jts1882 0 add goal threshold: only show goals above |minimum= 1361218 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = templateArgs['minimum'] or 1000 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) -- equivalent to {{Div col|colwidth=18em}} return frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } --return '<div class="div-col columns column-count column-count-3" style="' -- .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) -- equivalent to {{Div col end}} return frame:expandTemplate{ title = 'div col end' } --return '</div>' end return p c34fo9i1huf7n5dxu7r7lb3y4bbvcj4 1361219 1361218 2018-12-14T09:32:10Z en>Jts1882 0 logic!!! 1361219 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = templateArgs['minimum'] or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) -- equivalent to {{Div col|colwidth=18em}} return frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } --return '<div class="div-col columns column-count column-count-3" style="' -- .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) -- equivalent to {{Div col end}} return frame:expandTemplate{ title = 'div col end' } --return '</div>' end return p a9dkhysn7lk3r1wk66llclr4e68nsn9 1361220 1361219 2018-12-14T09:34:53Z en>Jts1882 0 fix type 1361220 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) -- equivalent to {{Div col|colwidth=18em}} return frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } --return '<div class="div-col columns column-count column-count-3" style="' -- .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) -- equivalent to {{Div col end}} return frame:expandTemplate{ title = 'div col end' } --return '</div>' end return p i0lsq8cffxgi73zmnu7e8jkhmyrqznu 1361221 1361220 2018-12-14T09:41:34Z en>Jts1882 0 add competition as parameter 1361221 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " [[" .. u['player'] .. "]]" -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) -- equivalent to {{Div col|colwidth=18em}} return frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } --return '<div class="div-col columns column-count column-count-3" style="' -- .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) -- equivalent to {{Div col end}} return frame:expandTemplate{ title = 'div col end' } --return '</div>' end return p 7tmn2jl1qaj1kvwj4mdlih5bkdth8c6 1361222 1361221 2018-12-14T21:37:04Z en>S.A. Julio 0 adjust name formatting 1361222 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) -- equivalent to {{Div col|colwidth=18em}} return frame:expandTemplate{ title = 'Div col', args = {colwidth="18em"} } --return '<div class="div-col columns column-count column-count-3" style="' -- .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) -- equivalent to {{Div col end}} return frame:expandTemplate{ title = 'div col end' } --return '</div>' end return p c7vwbevmdawp55wy1cq7kx5rcc3x1d8 1361223 1361222 2018-12-14T22:01:35Z en>S.A. Julio 0 try div tags 1361223 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 371ocag31hja77j43aapy6x67bie7sb 1361224 1361223 2018-12-14T22:30:34Z en>S.A. Julio 0 try to use singular 'goal' 1361224 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 0 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 7zf8qen8k8oipj1baknb73f1d2ic1az 1361225 1361224 2018-12-14T22:31:47Z en>S.A. Julio 0 adjust 1361225 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if goals == 0 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 3vvecr2pajxht69zvjxd2mlea6cwqol 1361226 1361225 2018-12-14T22:32:04Z en>S.A. Julio 0 restore 1361226 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 0 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 7zf8qen8k8oipj1baknb73f1d2ic1az 1361227 1361226 2018-12-14T22:34:55Z en>S.A. Julio 0 typo 1361227 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals local i = 4 while i < #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p pgpcurc98snhmb6i0lcd9hq4kjgx1ih 1361228 1361227 2018-12-15T07:28:11Z en>Jts1882 0 fix loop for total goals using for loop (the while <#v should have been <=#v) 1361228 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" local goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then goalscorers[#goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- sort selected goalscorers by number of goals table.sort( goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) -- output the lists of goalscorers by goal local goalNumber = 1000 local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p j6rq8mbwr973pnf82342e4bdfgf8r86 1361229 1361228 2018-12-15T09:57:43Z en>Jts1882 0 add secondary sort on country 1361229 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" p.goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals > 0 then p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end -- ====================sort selected goalscorers by number of goals======================= --table.sort( p.goalscorers, function( a, b ) return a['country'] > b['country'] end ) --table.sort( p.goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) --table.sort(p.goalscorers, local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- primary sort tied, resolve w secondary sort on 'country' return a.country < b.country end end table.sort(p.goalscorers, sort_function) if 1==1 then --return mw.dumpObject(p.goalscorers) end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p ggfx86sxg6or838za7jmykhjbktz001 1361230 1361229 2018-12-15T10:09:15Z en>Jts1882 0 separate selectGoalscorer function 1361230 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" --p.goalscorers = {} -- selected goalscorers meeting round and group criteris p.selectGoalscorers() -- ====================sort selected goalscorers by number of goals======================= --table.sort( p.goalscorers, function( a, b ) return a['country'] > b['country'] end ) --table.sort( p.goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) --table.sort(p.goalscorers, local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- primary sort tied, resolve w secondary sort on 'country' return a.country < b.country end end table.sort(p.goalscorers, sort_function) if 1==1 then --return mw.dumpObject(p.goalscorers) end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- select players meeting round and goal criteria function p.selectGoalscorers() data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 0 --local outputString = "" p.goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end --return p.goalscorers -- or is it available anyway end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p mpx19o2gce5pxdavixgk1fe62vqar5n 1361231 1361230 2018-12-15T10:13:20Z en>Jts1882 0 separate sortGoalscorers() function 1361231 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local outputString = "" --p.goalscorers = {} -- selected goalscorers meeting round and group criteris p.selectGoalscorers() -- ====================sort selected goalscorers by number of goals======================= --table.sort( p.goalscorers, function( a, b ) return a['country'] > b['country'] end ) --table.sort( p.goalscorers, function( a, b ) return a['goals'] > b['goals'] end ) p.sortGoalscorers() if 1==1 then --return mw.dumpObject(p.goalscorers) end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- select players meeting round and goal criteria function p.selectGoalscorers() data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 0 --local outputString = "" p.goalscorers = {} -- selected goalscorers meeting round and group criteris -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end --return p.goalscorers -- or is it available anyway end function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- primary sort tied, resolve w secondary sort on 'country' return a.country < b.country end end table.sort(p.goalscorers, sort_function) end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 85cpxysrp2lhx2wpfztiu5yxb2vfim8 1361232 1361231 2018-12-15T10:22:31Z en>Jts1882 0 separate outputGoalscorers() function and some clean-up 1361232 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers() data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 0 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end --return p.goalscorers -- it is available anyway end function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- primary sort tied, resolve w secondary sort on 'country' return a.country < b.country end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 9ujsaqkbk8aw91bnxeuv1td1velwmny 1361233 1361232 2018-12-15T10:25:05Z en>Jts1882 0 we don't want to list zero goals in rounds 1361233 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers() data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end --return p.goalscorers -- it is available anyway end function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- primary sort tied, resolve w secondary sort on 'country' return a.country < b.country end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p hleaahoie2eueeixkrd1mp5o79q8g3p 1361234 1361233 2018-12-15T10:37:38Z en>Jts1882 0 add tertiary sort on player name 1361234 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers() data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end --return p.goalscorers -- it is available anyway end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country --resolve w secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, return a.player < b.player --resolve w tertial sort on 'player' name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 9wydogkv62enh2fvqac2awep3ad9t4z 1361235 1361234 2018-12-15T10:47:01Z en>Jts1882 0 tertiary sort on second name of player unless single name 1361235 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers() data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end --return p.goalscorers -- it is available anyway end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country --resolve w secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, local names_a = mw.text.split( a.player, " ") local names_b = mw.text.split( b.player, " ") if not names_a[2] then names_a[2] = names_a[1] end -- for players with one name if not names_b[2] then names_b[2] = names_b[1] end return names_a[2] < names_b[2] -- sort on second name --return a.player < b.player --resolve w tertial sort on 'player' name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p s6jc19kjttl6fa9t9eccaydvwnajx1g 1361236 1361235 2018-12-15T11:58:12Z en>Jts1882 0 still isn't sorting single name players as expected 1361236 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers() data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end --return p.goalscorers -- it is available anyway end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertial sort on 'player' name local names_a = mw.text.split( a.player, " ") -- we don't want to sort on first name local names_b = mw.text.split( b.player, " ") -- so split names if not names_a[2] then names_a[2] = a.player end -- for players with one name if not names_b[2] then names_b[2] = b.player end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p mddqlzp6tirbzt313tswsjsjuxfmuk9 1361237 1361236 2018-12-15T13:22:34Z en>Jts1882 0 the reason single name players weren't sorted was because the test string had a redirect; now split after pipe, if one, before test 1361237 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers() data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested for k,v in pairs(data.goalscorers) do local goals = 0 -- goals > 0 is the flag to include the player if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goals = goals + v[i] i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals } end end --return p.goalscorers -- it is available anyway end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''\n" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''\n" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list linked flag icon player name local goalscorerString = "\n*" .. p.addLinkedIcon(frame, u['country']) .. " " .. u['player'] -- name outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p o3pz0wwpr79lg107kcvgq91njdb0gik 1361238 1361237 2018-12-15T15:03:15Z en>Jts1882 0 first pass at own goals 1361238 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end function p.owngoals(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = '<span> (against ' .. commentByRound else comment = comment .. ", " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = comment .. ")</span>" end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p stpntanjxi6eexrndsdieuet5p0pn6w 1361239 1361238 2018-12-15T15:31:14Z en>Jts1882 0 formatting of comment 1361239 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end function p.owngoals(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = '<span> (' .. commentByRound else comment = comment .. "; " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = comment .. ")</span>" end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 44frkce5f7htc1kg3a1flnzpl4brnv6 1361240 1361239 2018-12-15T15:40:09Z en>S.A. Julio 0 option for youth level 1361240 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end function p.owngoals(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = '<span> (' .. commentByRound else comment = comment .. "; " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = comment .. ")</span>" end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country, level } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p pvsqwm0q6t2ubc8wetfh6gh5sg5hnyc 1361241 1361240 2018-12-15T15:49:59Z en>S.A. Julio 0 partial restore 1361241 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end function p.owngoals(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = '<span> (' .. commentByRound else comment = comment .. "; " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = comment .. ")</span>" end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p atu6iaoge1lqekeb75nbw2in2hb111d 1361242 1361241 2018-12-15T16:02:01Z en>S.A. Julio 0 fix order 1361242 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end function p.owngoals(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = '<span> (' .. commentByRound else comment = comment .. "; " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = comment .. ")</span>" end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { level, country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p t9q2zunos8a7w8907bpkvwlkg2v7o5h 1361243 1361242 2018-12-15T16:03:00Z en>S.A. Julio 0 restore 1361243 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end function p.owngoals(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = '<span> (' .. commentByRound else comment = comment .. "; " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = comment .. ")</span>" end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p atu6iaoge1lqekeb75nbw2in2hb111d 1361244 1361243 2018-12-15T16:29:55Z en>Jts1882 0 add youth level parameter to country icon link 1361244 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end function p.owngoals(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = '<span> (' .. commentByRound else comment = comment .. "; " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = comment .. ")</span>" end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} return frame:expandTemplate{ title = icon , args = { level, country } } -- flag icon end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p t9q2zunos8a7w8907bpkvwlkg2v7o5h 1361245 1361244 2018-12-15T16:42:40Z en>Jts1882 0 fix for when youth parameter not set 1361245 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end function p.owngoals(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = '<span> (' .. commentByRound else comment = comment .. "; " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = comment .. ")</span>" end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame) -- output list of goalscorers local outputString = "" -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end if u['goals'] == 1 then outputString = outputString .. "\n'''" .. u['goals'] .. " goal'''" -- list caption 1 goal else outputString = outputString .. "\n'''" .. u['goals'] .. " goals'''" -- list caption end outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p ncn4d7bu7hglm4s2mh3ul97c8xg4acd 1361246 1361245 2018-12-15T17:15:00Z en>Jts1882 0 modify own goal list header output; add own goals to list off goals 1361246 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = '<span> (' .. commentByRound else comment = comment .. "; " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals = v[goalsCol] elseif group == "" then -- any group goals = v[goalsCol] end elseif round == "playoffs" then -- playoff round (redunant?) goals = v[goalsCol] else -- any other round goals = v[goalsCol] -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = comment .. ")</span>" end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p co33urihw46t1q99ibm32pwpyjwiytq 1361247 1361246 2018-12-15T17:22:37Z en>Jts1882 0 add getGoals handling of single value or table entry to other options 1361247 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = '<span> (' .. commentByRound else comment = comment .. "; " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] ) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] ) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] ) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = comment .. ")</span>" end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 9cnzi7j2dtq4vbbrndmvpo0530xlj3l 1361248 1361247 2018-12-15T17:41:16Z en>Jts1882 0 fix bracketing of comment element 1361248 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "; " .. commentByRound end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] ) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] ) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] ) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then comment = '<span> (' .. comment .. ')</span>' end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p tcmsctfityzeh3qizbskazcjvfu4r52 1361249 1361248 2018-12-15T18:14:56Z en>Jts1882 0 save with test sortComment function disabled 1361249 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. ", " .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] ) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] ) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] ) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then comment = '<span> (' .. comment .. ')</span>' -- p.sortComment(comment) else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end function p.sortComment(comment) local items = mw.text.split( comment, ",") if #items == 1 then return comment end for k,v in pairs(items) do items[k] = mw.text.trim(v) end table.sort(items, function(a,b) return a>b end) if (1==1) then return items[1].. items[2] ..items[3] end local list = "playing against " -- .. items(1) for i=2, #items-1 do list = list .. ", " .. items[i] end list = list .. " and " .. items(#items) return list end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 7f22kw1bqkixxg7ineyv4qcralt7yih 1361250 1361249 2018-12-15T20:37:13Z en>Jts1882 0 sort the own goals against countries; need to add first letter to uc 1361250 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] ) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] ) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] ) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end function p.sortComment(comment) local items_raw = mw.text.split( comment, ",") if #items_raw == 1 then --return comment end local items = {} for k,v in pairs(items_raw) do items[k] = string.lower(mw.text.trim(v)) end table.sort(items, function(a,b) return a<b end) --if (1==1) then return items[1].. items[2] ..items[3] end local list = "playing against " .. items[1] if items[2] and items[3] then for i=2, #items-1 do list = list .. ", " .. items[i] end list = list .. " and " .. items[#items] end return list end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end return p 3gar67kpj2s0aew3vq2m9k5sq9e7oyc 1361251 1361250 2018-12-15T20:41:44Z en>Jts1882 0 upper case the first letter of the countries 1361251 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] ) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] ) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] ) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end function p.sortComment(comment) local items_raw = mw.text.split( comment, ",") if #items_raw == 1 then --return comment end local items = {} for k,v in pairs(items_raw) do items[k] = string.lower(mw.text.trim(v)) end table.sort(items, function(a,b) return a<b end) --if (1==1) then return items[1].. items[2] ..items[3] end local list = "playing against " .. p.firstToUpper(items[1]) if items[2] and items[3] then for i=2, #items-1 do list = list .. ", " .. p.firstToUpper(items[i]) end list = list .. " and " .. p.firstToUpper(items[#items]) end return list end --[[ the goals can be a single number or a table {number of goals, string about the goals} ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] else return u, "" end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p leju5ld0rtj81w84ffx6yv11a9lefgh 1361252 1361251 2018-12-16T09:58:57Z en>Jts1882 0 produce alphabetically sorted string of own goal countries 1361252 Scribunto text/plain require('Module:No globals'); local p = {} local error_msg = '<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>'; -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] ) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] ) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] ) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] ) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u) if type(u) == 'table' then return u[1], u[2] -- return number of goals, comment else return u, "" -- return number of goals, empty string end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "playing against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p pp4qwwxcn7cn0dlbazel69ekqg60cmc 1361253 1361252 2018-12-16T10:16:37Z en>Jts1882 0 add error message for invalid goals 1361253 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg(message) if message ~= "" then return'<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. message .. '</span>'; else return "" end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country if p.errorString ~= "" then return p.error_msg(p.errorString) end return p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , v[1]) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , v[1]) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , v[1]) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , v[1]) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "playing against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 161j0bv3fa6k5ugg5dxbaqak64qn8x1 1361254 1361253 2018-12-16T10:19:41Z en>Jts1882 0 return zero goals if error 1361254 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg(message) if message ~= "" then return'<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. message .. '</span>'; else return "" end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country if p.errorString ~= "" then return p.error_msg(p.errorString) end return p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , v[1]) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , v[1]) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , v[1]) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , v[1]) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "playing against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 16mbxymht33bqwams0f1eum20g0kgbs 1361255 1361254 2018-12-16T10:22:49Z en>Jts1882 0 add type checking 1361255 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg(message) if message ~= "" then return'<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. message .. '</span>'; else return "" end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country if p.errorString ~= "" then return p.error_msg(p.errorString) end return p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , v[1]) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , v[1]) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , v[1]) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , v[1]) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "playing against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p tnj5urk6qjl6l2omgsyqr2m6l1xl6og 1361256 1361255 2018-12-16T10:36:27Z en>Jts1882 0 minor formating 1361256 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg(message) if message ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. message .. '</span>'; else return "" end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country if p.errorString ~= "" then return p.error_msg(p.errorString) end return p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , v[1]) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , v[1]) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , v[1]) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , v[1]) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "playing against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p edsmbyhkscc2jx63qfcboe537tl5gfw 1361257 1361256 2018-12-16T10:42:12Z en>Jts1882 0 move error handing to catch own goals 1361257 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg(message) if message ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. message .. '</span>'; else return "" end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers if p.errorString ~= "" then return p.error_msg(p.errorString) end return outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) --data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' return p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , v[1]) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , v[1]) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , v[1]) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , v[1]) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "playing against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p a65u03mpqp6wtmasxvjepoa52hapad8 1361258 1361257 2018-12-16T10:56:04Z en>Jts1882 0 simplify error handling return 1361258 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) return p.error_msg() or p._owngoals(frame) end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , v[1]) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , v[1]) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , v[1]) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , v[1]) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "playing against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p p6agxiy0se81nvjmbkkd5ludfyxww5a 1361259 1361258 2018-12-16T11:06:01Z en>Jts1882 0 logic 1361259 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , v[1]) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , v[1]) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , v[1]) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , v[1]) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "playing against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 1fzvyv79wo7ejdl7cblnkbvmrcy64lp 1361260 1361259 2018-12-16T11:28:25Z en>S.A. Julio 0 simplify, "against" suffices and saves space 1361260 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , v[1]) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , v[1]) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , v[1]) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , v[1]) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {"3"} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p jk7vxnjaxaizcpbmend0kctv966f56h 1361261 1361260 2018-12-16T15:56:47Z en>Jts1882 0 make column width a variable; set to 2 for own goals 1361261 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , v[1]) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , v[1]) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , v[1]) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , v[1]) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) local columns = 3 if og == "OG" then columns = 2 end return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {columns} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p bbjqgsjmkn8ko2aj5qbr0umquqjclce 1361262 1361261 2019-01-01T18:10:04Z en>S.A. Julio 0 test 1361262 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , v[1]) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , v[1]) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , v[1]) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , v[1]) -- should also hand playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=v[1], country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name -- we don't want to test the name in a redirect, so get name after pipe if there is one local test_a, test_b = a.player, b.player if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p j4kzf6h3vq5qqdhej0yxka4efz2nlhv 1361263 1361262 2019-01-03T08:28:30Z en>Jts1882 0 first pass on more refined player name sorting 1361263 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=playerName, country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer (u) if type(u) == 'table' and type(u[1]) == 'string' then return u[1], u[2] -- return player name, player sorting alias elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid goals entry for player " .. u or u[1] or "unknown" return "", "" end end function p.getPlayerSortName (u) local playerName, sortName = p.getPlayer (u) -- get player name and supplied sort name if available if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' if (a.country < b.country) then -- secondary sort on 'country' return true elseif (a.country > b.country) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player) -- get player name for sorting local player_b = p.getPlayerSortName(b.player) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p r1tzraupxtcn6eqtkox8sylck9psh1j 1361264 1361263 2019-01-03T08:43:06Z en>Jts1882 0 sort on country name, not three-letter code 1361264 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=playerName, country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer (u) if type(u) == 'table' and type(u[1]) == 'string' then return u[1], u[2] -- return player name, player sorting alias elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid goals entry for player " .. u or u[1] or "unknown" return "", "" end end function p.getPlayerSortName (u) local playerName, sortName = p.getPlayer (u) -- get player name and supplied sort name if available if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player) -- get player name for sorting local player_b = p.getPlayerSortName(b.player) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p mb374yvmp77ixh7xj02n9rphvcjy3ar 1361265 1361264 2019-01-03T10:22:59Z en>Jts1882 0 second pass (add alias for sorting to selected player table) 1361265 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end function p.getPlayerSortName (playerName, sortName) --local playerName, sortName = p.getPlayer(u) -- get player name and supplied sort name if available --[[if sortName ~= "" then p.errorString = p.errorString .. "\n\nWe have playerName=" .. playerName .. " and sortName=" .. sortName end ]] if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return playerName --names[1] .. " (single name)" -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 15077525ubomdgeapr34urmgazwzk1e 1361266 1361265 2019-01-03T10:53:06Z en>Jts1882 0 dewikify names for sorting, force lower case 1361266 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then --comment = '<span> (' .. comment .. ')</span>' comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end p.goalscorers[#p.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if u['goals'] ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. u['goals'] .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p lftzbwpexcec2l49w8leora9necu3vk 1361267 1361266 2019-01-03T11:28:34Z en>Jts1882 0 store own goals as negative number in selected table (allows proper sort order, 1 at top, most own goals at bottom) 1361267 Scribunto text/plain require('Module:No globals'); local p = {} p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local templateArgs = {} -- contains arguments from template invoking module local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then templateArgs[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'..templateArgs[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(templateArgs['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = templateArgs['round'] or "all" -- round = all(empty)|group|playoffs local group = templateArgs['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers p.goalscorers[#p.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(p.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(p.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p m8x68tefxvilfoatp8sxlj5iaubgq2c 1361268 1361267 2019-01-04T09:51:36Z en>Jts1882 0 reorganise parameters using g[args|goalscorers|etc] for parameters with module scope 1361268 Scribunto text/plain require('Module:No globals'); local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list -- p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.outputGoalscorers(frame) .. "" --TODO add intermediate heading? .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or 1 -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end local goalString = " goal" if og == "OG" then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p jt3yyqw2mezee16cprc1swpa2caa6mk 1361269 1361268 2019-01-04T10:30:29Z en>Jts1882 0 change how own goals handled - append to integrated same select list so total goals can be counted - add preliminary output of total gaols 1361269 Scribunto text/plain require('Module:No globals'); local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." local outputString = totalGoalString .. p.outputGoalscorers(frame) -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p p067d8bcktmyvao1liznb8hfpzaftyc 1361270 1361269 2019-01-04T11:07:18Z en>Jts1882 0 modify introductory text according to parameters 1361270 Scribunto text/plain require('Module:No globals'); local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), at an average of #GOALS/#MATCHES per match. local ongoing = g.args['ongoing'] local matches = g.args['matches'] local text = "There " if g.totalGoals == 1 then if ongoing then text = text .. "has been " else text = text .. "was " end else if ongoing then text = text .. "have been " else text = text .. "were " end end text = text .. tostring(g.totalGoals) .. " goals scored" if matches then local average = tostring (g.totalGoals/tonumber(matches)) text = text .. " in " .. matches .. ", at an average of " .. average .. " goals per match." else text = text .. "." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p hubwxr6z6u937llz5hh57vggmkzd773 1361271 1361270 2019-01-04T11:48:30Z en>Jts1882 0 edits to introductory sentence (average rounding etc) 1361271 Scribunto text/plain require('Module:No globals'); local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), at an average of #GOALS/#MATCHES per match. local ongoing = g.args['ongoing'] local matches = g.args['matches'] local text1 = "" if g.totalGoals == 1 then if ongoing then text1 = "has been" else text1 = "was" end else if ongoing then text1 = "have been" else text1 = "were" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = tostring (g.totalGoals/tonumber(matches)) text = text .. string.format(" in %d matches, at an average of %.2f goals per match.", matches, average) else text = text .. "." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 741y63n3c22h1m9mraud1w9ag71yv6o 1361272 1361271 2019-01-04T11:56:23Z en>Jts1882 0 use yesno module to accept variety of true/false yes/no input 1361272 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]=v --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), at an average of #GOALS/#MATCHES per match. local ongoing = yesno(g.args['ongoing']) local matches = g.args['matches'] local text1 = "" if g.totalGoals == 1 then if ongoing then text1 = "has been" else text1 = "was" end else if ongoing then text1 = "have been" else text1 = "were" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = tostring (g.totalGoals/tonumber(matches)) text = text .. string.format(" in %d matches, at an average of %.2f goals per match.", matches, average) else text = text .. "." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p a9kjqx7opi80hxizak6rgiw5w4mb2zx 1361273 1361272 2019-01-04T12:01:31Z en>Jts1882 0 use mw.text.trim() as positional parameters are not trimmed like named parameters 1361273 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), at an average of #GOALS/#MATCHES per match. local ongoing = yesno(g.args['ongoing']) local matches = g.args['matches'] local text1 = "" if g.totalGoals == 1 then if ongoing then text1 = "has been" else text1 = "was" end else if ongoing then text1 = "have been" else text1 = "were" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = tostring (g.totalGoals/tonumber(matches)) text = text .. string.format(" in %d matches, at an average of %.2f goals per match.", matches, average) else text = text .. "." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p p0kztqy7jjdw137b9iwps1ch8t9injk 1361274 1361273 2019-01-04T18:50:40Z en>S.A. Julio 0 test using data.updated 1361274 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local dateUpdated = data.updated['1'] local matches = g.args['matches'] local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = tostring (g.totalGoals/tonumber(matches)) text = text .. string.format(" in %d matches, for an average of %.2f goals per match.", matches, average) else text = text .. "." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p dmwcwuhe8btah2jbtqdpbyvr81v2rpz 1361275 1361274 2019-01-04T18:52:06Z en>S.A. Julio 0 adjust 1361275 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local dateUpdated = data.updated['date'] local matches = g.args['matches'] local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = tostring (g.totalGoals/tonumber(matches)) text = text .. string.format(" in %d matches, for an average of %.2f goals per match.", matches, average) else text = text .. "." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 6j9ai8wpk3yssvhpkqiptay6tgeyfpg 1361276 1361275 2019-01-04T19:00:07Z en>S.A. Julio 0 display when last updated if ongoing 1361276 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local dateUpdated = data.updated['date'] local matches = g.args['matches'] local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = tostring (g.totalGoals/tonumber(matches)) text = text .. string.format(" in %d matches, for an average of %.2f goals per match", matches, average) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. dateUpdated .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p gvzp8x188stuclirp7a88m5lgharqxe 1361277 1361276 2019-01-05T10:28:10Z en>Jts1882 0 remove trailing zeros from average; singular if average=1 1361277 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local dateUpdated = data.updated['date'] local matches = g.args['matches'] local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = tostring (g.totalGoals/tonumber(matches)) local plural = "s" if tonumber(string.format("%.2g",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %.2g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. dateUpdated .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 4hp3kex1ut6fmyltlmose3la29c8yxn 1361278 1361277 2019-01-06T09:30:51Z en>Jts1882 0 is %0.3g better? 1361278 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local dateUpdated = data.updated['date'] local matches = g.args['matches'] local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = tostring (g.totalGoals/tonumber(matches)) local plural = "s" if tonumber(string.format("%.2g",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %.3g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. dateUpdated .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p ei27mnh6hpqbv2okant5gji8f5vznk5 1361279 1361278 2019-01-06T10:17:59Z en>Jts1882 0 Template:Goalscorers/sandbox2 1361279 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local dateUpdated = data.updated['date'] local matches = g.args['matches'] local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = tostring (g.totalGoals/tonumber(matches)) local plural = "s" if tonumber(string.format("%.2g",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %3.3g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. dateUpdated .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p d50cmndxhjdzlyqb8trs7qmdi1pqo9n 1361280 1361279 2019-01-06T12:42:26Z en>Jts1882 0 use %.ng (with n=2 for average < 1 and n=3 otherwise 1361280 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local dateUpdated = data.updated['date'] local matches = g.args['matches'] local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. dateUpdated .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 4wudtw7bdin9czra9h4za6wnx8bg8f4 1361281 1361280 2019-01-09T08:20:33Z en>Jts1882 0 add function getNumberMatches (preliminary step for using module data) 1361281 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. dateUpdated .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p c7go6mau5z21yq3sz70vjd4k8wzkgo1 1361282 1361281 2019-01-09T08:32:34Z en>Jts1882 0 reorganise - make sure data available for get matches function 1361282 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. dateUpdated .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or 'complete' -- assume completed if missing return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc (could be numbers as string) local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 19bkfkblnczq30ccf3fvfj466qpi4bb 1361283 1361282 2019-01-09T09:09:48Z en>Jts1882 0 first pass of match counting; update dates is incomplete; need the match information in the Test competition 1361283 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. dateUpdated .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or 'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames else matches = matches + v[1] end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames else -- single group only matches = data.updated.group[group][1] dateUpdated = data.updated.group[group][2] end else -- any other round matches = data.updated[round][1] dateUpdated = data.updated[round][2] end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 896m3isi0evgkagvfe0ddft3f3vejuw 1361284 1361283 2019-01-09T11:59:13Z en>S.A. Julio 0 test [[Module:Date]] 1361284 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('mdy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or 'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames else matches = matches + v[1] end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames else -- single group only matches = data.updated.group[group][1] dateUpdated = data.updated.group[group][2] end else -- any other round matches = data.updated[round][1] dateUpdated = data.updated[round][2] end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p cg06ynoexs2859g52imb2fsy55qisia 1361285 1361284 2019-01-09T12:00:01Z en>S.A. Julio 0 fix 1361285 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or 'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames else matches = matches + v[1] end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames else -- single group only matches = data.updated.group[group][1] dateUpdated = data.updated.group[group][2] end else -- any other round matches = data.updated[round][1] dateUpdated = data.updated[round][2] end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p tiar89r02jq6szyvcb2rnco5zbt4gjj 1361286 1361285 2019-01-09T12:06:33Z en>S.A. Julio 0 test for mdy option 1361286 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end local dmy = yesno(g.args['dmy']) if dmy then dmy = mdy else dmy = dmy end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text(dmy) .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or 'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames else matches = matches + v[1] end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames else -- single group only matches = data.updated.group[group][1] dateUpdated = data.updated.group[group][2] end else -- any other round matches = data.updated[round][1] dateUpdated = data.updated[round][2] end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 973xlvg2y955jnurjjh5vl3epfxgvyu 1361287 1361286 2019-01-09T12:09:53Z en>S.A. Julio 0 fix 1361287 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end local dmy = yesno(g.args['dmy']) if dmy then dmy = 'mdy' else dmy = 'dmy' end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text(dmy) .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or 'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames else matches = matches + v[1] end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames else -- single group only matches = data.updated.group[group][1] dateUpdated = data.updated.group[group][2] end else -- any other round matches = data.updated[round][1] dateUpdated = data.updated[round][2] end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p cga9wjwmeaxuj556e7591dxpnovml6w 1361288 1361287 2019-01-09T12:10:25Z en>S.A. Julio 0 did not work, restore for now 1361288 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or 'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames else matches = matches + v[1] end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames else -- single group only matches = data.updated.group[group][1] dateUpdated = data.updated.group[group][2] end else -- any other round matches = data.updated[round][1] dateUpdated = data.updated[round][2] end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p tiar89r02jq6szyvcb2rnco5zbt4gjj 1361289 1361288 2019-01-09T12:19:22Z en>S.A. Julio 0 another try 1361289 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end local dateFormat = yesno(g.args['mdy']) if dateFormat then dateFormat = 'mdy' else dateFormat = 'dmy' end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or 'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames else matches = matches + v[1] end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames else -- single group only matches = data.updated.group[group][1] dateUpdated = data.updated.group[group][2] end else -- any other round matches = data.updated[round][1] dateUpdated = data.updated[round][2] end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 5a14ema833nza6thxuk66p7g3zs09t6 1361290 1361289 2019-01-09T12:21:40Z en>S.A. Julio 0 restore once more 1361290 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or 'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames else matches = matches + v[1] end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames else -- single group only matches = data.updated.group[group][1] dateUpdated = data.updated.group[group][2] end else -- any other round matches = data.updated[round][1] dateUpdated = data.updated[round][2] end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " and " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p tiar89r02jq6szyvcb2rnco5zbt4gjj 1361291 1361290 2019-01-10T11:54:54Z en>S.A. Julio 0 use ampersand to be clearer when "Bosnia and Herzegovina" mentioned 1361291 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or 'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames else matches = matches + v[1] end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames else -- single group only matches = data.updated.group[group][1] dateUpdated = data.updated.group[group][2] end else -- any other round matches = data.updated[round][1] dateUpdated = data.updated[round][2] end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p fdf5c258io4l5oxai0umazmm6wkecqa 1361292 1361291 2019-01-11T13:18:54Z en>Jts1882 0 get most recent update for select rounds/groups (this could do with double checking) 1361292 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") return string.lower(name) end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 40rt2hvtdw1bshrnrcvwvqd4b0um07n 1361293 1361292 2019-01-11T13:29:22Z en>Jts1882 0 replace special characters from list (on line 299) [needs testing] 1361293 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , {"é", "e"} } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, k, v) end return string.lower(name) -- force lower case and return end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p po9s3kfv05w5rtpjjxhoikdizs1pyfg 1361294 1361293 2019-01-11T13:38:18Z en>Jts1882 0 fix logic of special character sorting (using v[1], v[2] pairs not k=v 1361294 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , {"é", "e"} } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return string.lower(name) -- force lower case and return end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p qbv040t5z1cxc30hw1wgogx2b2gyoa6 1361295 1361294 2019-01-11T14:01:19Z en>Jts1882 0 fix all group option 1361295 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end -- remove wikitext [[ and ]] and return as lowercase function p.stripPlaySortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , {"é", "e"} } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return string.lower(name) -- force lower case and return end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.stripPlaySortName (playerName) sortName = p.stripPlaySortName (sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p aslqk7z9ch9ngjgfa5o4dwk42tzqf4d 1361296 1361295 2019-01-12T17:23:14Z en>Jts1882 0 convert to lower case before special character replacement; rename function 1361296 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") name =string.lower(name) -- force lower case and return local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , {"é", "e"} } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p t94x3moklhaje41sz00k1ljp0824p5a 1361297 1361296 2019-01-14T16:13:50Z en>S.A. Julio 0 add more special characters 1361297 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") name =string.lower(name) -- force lower case and return local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p egoka693y49u29o5w7lzqd9pc7stmqe 1361298 1361297 2019-01-14T16:18:45Z en>S.A. Julio 0 test 1361298 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") name =string.lower(name) -- force lower case and return local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "Ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 5w2go8fnr71zj3a4foybdo9d1ewpimj 1361299 1361298 2019-01-14T16:20:24Z en>S.A. Julio 0 reorder 1361299 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end name =string.lower(name) -- force lower case and return return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 6yo8dsftrmj8urftjq9bu07f0oleaym 1361300 1361299 2019-01-14T16:21:36Z en>S.A. Julio 0 restore 1361300 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") name =string.lower(name) -- force lower case and return local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p egoka693y49u29o5w7lzqd9pc7stmqe 1361301 1361300 2019-01-14T16:45:42Z en>Jts1882 0 use unicode function for lower case 1361301 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 6kjvsxn6n1d6n0ws4zsytxcat760npf 1361302 1361301 2019-01-15T12:31:51Z en>S.A. Julio 0 test for further line 1361302 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end local further = data.intro['further_text'] if further then further = " " .. further end return text, further --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p o6rlckakp3d8duhxmory8i5bfiq4eo0 1361303 1361302 2019-01-15T12:32:19Z en>S.A. Julio 0 restore 1361303 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 6kjvsxn6n1d6n0ws4zsytxcat760npf 1361304 1361303 2019-01-15T12:38:27Z en>S.A. Julio 0 try once more 1361304 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end local further = data.updated['further_text'] if further then further = " " .. further end return text, further --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p l5ua775qwultlv82e3ck3l34oqd3h7n 1361305 1361304 2019-01-15T12:42:58Z en>S.A. Julio 0 adjust 1361305 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end local further = data.updated['further_text'] if further ~= "" then further = " " .. further end return text, further --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p dr6sugoo6y2e8ibg08s2kd6yungotol 1361306 1361305 2019-01-15T12:48:33Z en>S.A. Julio 0 adjust 1361306 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end local further = data.updated['further_text'] if further ~= "" then text = text .. " " .. further end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p qshjb87hwad4uhkknhwrw7cef0i88m3 1361307 1361306 2019-01-15T12:49:48Z en>S.A. Julio 0 restore 1361307 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = "" return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country } } else return frame:expandTemplate{ title = icon , args = { country } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 6kjvsxn6n1d6n0ws4zsytxcat760npf 1361308 1361307 2019-01-15T14:01:47Z en>Jts1882 0 add prototype footer function and add flag variant parameter to flagicon call (needs to be set though) 1361308 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p 21r879dghf1j7va8aip004w0e1tgnsk 1361309 1361308 2019-01-15T17:31:27Z en>Jts1882 0 use data parameter 1361309 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end return p goki3196t324792ashqbkkkkrwc9cm8 1361310 1361309 2019-01-15T18:07:39Z en>Jts1882 0 add prototype list function 1361310 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end --[[ use data supplied by template ]] function p.list(frame) getArgs(frame) local output = "" --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local number = 30 --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] while number > 0 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' assists'] if entry then -- place the list for each number here end number = number -1 end return output end return p t86tdrjp1kvcab6nx9bnokppyma4s13 1361311 1361310 2019-01-16T09:06:18Z en>Jts1882 0 intro text for goals and average for list() function (using template data) 1361311 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end --[[ use data supplied by template ]] function p.list(frame) getArgs(frame) local output = "" --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end --[[ TODO singular if goal. But would the template be used if only one goal or assist? number of players scoring further extra ]] local text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) if g.args['bold'] then text = text .. "Players highlighted in '''bold''' are still active in the competition." end local number = 30 --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] while number > 0 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' assists'] if entry then -- place the list for each number here end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} return text .. output end return p qfpy8pxl6aowfjq4x9xz3inj3cmcs3o 1361312 1361311 2019-01-16T09:23:47Z en>Jts1882 0 format output in list() 1361312 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end --[[ use data supplied by template ]] function p.list(frame) getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end --[[ TODO singular if goal. But would the template be used if only one goal or assist? number of players scoring further extra ]] local text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) if g.args['bold'] then text = text .. "Players highlighted in '''bold''' are still active in the competition." end local output = "\n" local number = 30 --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] while number > 0 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' assists'] if entry then -- do we have goals/assits for this number -- place the list for each number here output = output .. "\n'''" .. tostring(number) .. " goals:'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} return text .. output end return p 4zbj6g4anxmu8m1h2vol56lkqivowau 1361313 1361312 2019-01-16T10:09:30Z en>Jts1882 0 handle singular goal/assist; add own goals; add source 1361313 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 --local templateArgs = {} -- contains arguments from template invoking module p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] -- hard code to example data local data = {} --require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end --[[ use data supplied by template ]] function p.list(frame) getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end --[[ TODO singular if goal. But would the template be used if only one goal or assist? number of players scoring further extra ]] local text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) if g.args['bold'] then text = text .. "Players highlighted in '''bold''' are still active in the competition." end --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' assists'] or g.args[number .. ' goal'] or g.args[number .. ' assist'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] if source then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 081d6jtpa1ghvx9iii0pi9x2x7p8le0 1361314 1361313 2019-01-16T10:19:33Z en>Jts1882 0 reorganise: handle data source in main(), separate function to handle module or template datasource 1361314 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end --[[ TODO singular if goal. But would the template be used if only one goal or assist? number of players scoring further extra ]] local text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) if g.args['bold'] then text = text .. "Players highlighted in '''bold''' are still active in the competition." end --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' assists'] or g.args[number .. ' goal'] or g.args[number .. ' assist'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] if source then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p c1unwk95l6ppai4z5hxnearl2rtb004 1361315 1361314 2019-01-16T11:01:05Z en>Jts1882 0 don't display goals scored line if assists 1361315 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end --[[ TODO singular if goal. But would the template be used if only one goal or assist? number of players scoring further extra ]] local text = "" if not g.args['asssists'] then string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end if g.args['bold'] then text = text .. "Players highlighted in '''bold''' are still active in the competition." end --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' assists'] or g.args[number .. ' goal'] or g.args[number .. ' assist'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] if source then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 2qlc9sdmq8ez6dvhghcglpul2fw9dnx 1361316 1361315 2019-01-16T11:04:15Z en>Jts1882 0 fix 1361316 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end --[[ TODO singular if goal. But would the template be used if only one goal or assist? number of players scoring further extra ]] local text = "" if g.args['goals'] then string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end if g.args['bold'] then text = text .. "Players highlighted in '''bold''' are still active in the competition." end --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' assists'] or g.args[number .. ' goal'] or g.args[number .. ' assist'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] if source then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p n2thia2xuicannbnbnui5q4exk1oz3p 1361317 1361316 2019-01-16T11:21:04Z en>Jts1882 0 extra/further/bold to new function; add use in module data function(using template parameters 1361317 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. "Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' assists'] or g.args[number .. ' goal'] or g.args[number .. ' assist'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] if source then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p co9ms5h30gg8aje36xf5kn3mtdwl5mz 1361318 1361317 2019-01-16T11:26:39Z en>Jts1882 0 add space to txt 1361318 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else text = text .. " (as of " .. Date(dateUpdated):text('dmy') .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' assists'] or g.args[number .. ' goal'] or g.args[number .. ' assist'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] if source then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p mcdultbn7oyaobmkkukm70dojks0hcw 1361319 1361318 2019-01-16T11:50:54Z en>Jts1882 0 add data format parameter handling 1361319 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = (g.args['mdy'] and 'mdy') or 'dmy' text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' assists'] or g.args[number .. ' goal'] or g.args[number .. ' assist'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] if source then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p czrjjfujif1hzdiq8mo2pg3xjcinvaz 1361320 1361319 2019-01-16T11:59:37Z en>Jts1882 0 add clean sheet handling 1361320 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = (g.args['mdy'] and 'mdy') or 'dmy' text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheet'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p hwleuku4cirqvhx17pt83ktk5izqpjm 1361321 1361320 2019-01-16T16:11:31Z en>Jts1882 0 date format with following precedence: template parameter > module subpage value > default (dmy) 1361321 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if g.args['mdy'] then dateFormat = "mdy" end -- template param overrides text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheet'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 1271nvzvyzmh41lh3zgx4w7k0zio57c 1361322 1361321 2019-01-16T19:09:00Z en>S.A. Julio 0 test adjustment w/ mdy template parameter 1361322 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == "false" then dateFormat = "dmy" else dateFormat = "mdy" end -- template param overrides text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheet'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p mk0mwrvl4i32b5raa8ikuncwlzp61qx 1361323 1361322 2019-01-16T19:13:11Z en>S.A. Julio 0 adjust 1361323 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == false then dateFormat = "dmy" else dateFormat = "mdy" end -- template param overrides text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheet'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p dto86ryvzn5i2qesvrhq7h3yzgg7imn 1361324 1361323 2019-01-16T19:15:14Z en>S.A. Julio 0 reorder 1361324 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else dateFormat = "dmy" end -- template param overrides text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheet'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p k4js9jjy5nzw0nkhjhhj2twypk7cctg 1361325 1361324 2019-01-16T19:18:52Z en>S.A. Julio 0 adjust 1361325 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheet'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assits for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. ":'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p imexeuoyjyn8wifo9vcsut5badqpbz5 1361326 1361325 2019-01-16T19:33:24Z en>S.A. Julio 0 unnecessary colon 1361326 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheet'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p slm8tyhfsszpvg1t11qfdst5tvnptwn 1361327 1361326 2019-01-16T19:35:47Z en>S.A. Julio 0 test 1361327 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheet'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p rziqgsvc464lr5gk2j1eorurftkpl52 1361328 1361327 2019-01-16T19:36:00Z en>S.A. Julio 0 rv 1361328 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheet'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p slm8tyhfsszpvg1t11qfdst5tvnptwn 1361329 1361328 2019-01-16T19:37:40Z en>S.A. Julio 0 adjust 1361329 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or g.args['clean sheets'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p o2wvuxdwyaxi7un32mmaxwjy3fc11aj 1361330 1361329 2019-01-16T19:41:18Z en>S.A. Julio 0 rmv, sentence unnecessary for assists 1361330 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 5wczwqqvzithwyl2nfbunztjrrzz6ft 1361331 1361330 2019-01-16T19:42:06Z en>S.A. Julio 0 restore 1361331 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheet'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p slm8tyhfsszpvg1t11qfdst5tvnptwn 1361332 1361331 2019-01-16T19:42:27Z en>S.A. Julio 0 fix 1361332 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 3d1ygyl5mpqeyl9m4n6q8k1mnwa41ji 1361333 1361332 2019-01-18T09:39:42Z en>Jts1882 0 add parse comment (with no parsing yet) 1361333 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], p.parseComment(u[2]) -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) return comment end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p do32em42ka6hy9bxujs2tmi534zb0l3 1361334 1361333 2019-01-18T10:07:19Z en>Jts1882 0 preprocess comment so uses templates 1361334 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], p.parseComment(u[2]) -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- frame:preprocess( string ) -- we have something like "{{efn-ua|name=goals}}" local value = string.match(comment, "{{(.+)}}" ) if value == 1 then local split = mw.text.split( value, "|", true ) return split[1] .. ", " .. split[2] --frame:expandTemplate{ title = title, args = table } end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p f1nqbz1qcagc4wudrjto2ayemcfp846 1361335 1361334 2019-01-18T10:56:14Z en>Jts1882 0 look for a comment with a note 1361335 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=comment} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], p.parseComment(u[2]) -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn-ua" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p fok29gardj6iwkx7oknpug2hpd45doo 1361336 1361335 2019-01-18T11:13:25Z en>Jts1882 0 move parse comment so only done for selected players 1361336 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span> (' .. comment .. ')</span>' end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p oxfo3sfe5vo10n4n1wosjlupewy6pa3 1361337 1361336 2019-01-18T12:42:47Z en>Jts1882 0 don't put parenthesis around comments except for own goals 1361337 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p islwxgmvwly40h0ykdkf8an3qjhhak1 1361338 1361337 2019-01-18T17:32:59Z en>Jts1882 0 handle flag variants 1361338 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ü", "u" } , { "é", "e" } , { "đ", "d" }, { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p ba8jpg78k1q07e49zjje38f5dbdibkp 1361339 1361338 2019-01-18T18:46:55Z en>S.A. Julio 0 add special character 1361339 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p tp42s50hrxocw33kswby399zjgrdg8k 1361340 1361339 2019-01-19T13:20:10Z en>S.A. Julio 0 add special character 1361340 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "" if group == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p grc0o9mqburnt13678rhlktd39u15d0 1361341 1361340 2019-01-20T09:49:35Z en>Jts1882 0 fix date sorting for tenses in introductory sentence 1361341 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p jsg5js7nbp1a9z9t7bt5n2p9czvneaq 1361342 1361341 2019-01-20T10:29:14Z en>S.A. Julio 0 add more special characters 1361342 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p ey7qtxkczi01hktjyueqg2fxxiq2c0d 1361343 1361342 2019-01-21T14:33:29Z en>S.A. Julio 0 add special character 1361343 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p rlg3wgwxl47pkhabar6v92xaircfykw 1361344 1361343 2019-01-22T07:23:24Z en>S.A. Julio 0 add special characters 1361344 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p mkumin9rmrwgrgcra71b572vg3t89al 1361345 1361344 2019-01-22T07:25:59Z en>S.A. Julio 0 adjust 1361345 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "i̇", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 4cbau68iwlr2o77hfvzfq4j3n6u2a84 1361346 1361345 2019-01-22T07:34:43Z en>S.A. Julio 0 restore 1361346 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local text1 = "" if g.totalGoals == 1 then if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goals scored", text1, g.totalGoals) if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local plural = "s" if tonumber(string.format("%.2f",average))==1 then plural = "" end text = text .. string.format(" in %d matches, for an average of %."..precision.."g goal%s per match", matches, average, plural) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p mkumin9rmrwgrgcra71b572vg3t89al 1361347 1361346 2019-01-22T07:58:00Z en>S.A. Julio 0 support 1 goal/1 match wording 1361347 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goal%s scored", text1, g.totalGoals, pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p aktrjs4miua3fzf0ddpbycgk3vywnsn 1361348 1361347 2019-01-22T09:15:55Z en>Jts1882 0 bold active players 1361348 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goal%s scored", text1, g.totalGoals, pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i < #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end -- wikitext for bullet list local styleString = "" if playerActive then styleString = ' style="font-weight:bold;" ' end local goalscorerString = '\n*<span' .. styleString ..'>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p h5whuzvvet12pyy17nbfkppzu5z81jw 1361349 1361348 2019-01-22T09:57:47Z en>Jts1882 0 add the last name to the sort name (<= not < ) 1361349 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %d goal%s scored", text1, g.totalGoals, pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end -- wikitext for bullet list local styleString = "" if playerActive then styleString = ' style="font-weight:bold;" ' end local goalscorerString = '\n*<span' .. styleString ..'>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p syi081b9989lm4lpqf9tmafji7xxcxn 1361350 1361349 2019-01-22T10:31:22Z en>Jts1882 0 format number 1,234 using mw.getLanguage('en'):formatNum() 1361350 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it else -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end -- wikitext for bullet list local styleString = "" if playerActive then styleString = ' style="font-weight:bold;" ' end local goalscorerString = '\n*<span' .. styleString ..'>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 9aht375dcszf4gokkqz8r8n0oymvik9 1361351 1361350 2019-01-22T13:39:36Z en>Jts1882 0 don't sort certain countries (this needs checking) 1361351 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "KOR" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end -- wikitext for bullet list local styleString = "" if playerActive then styleString = ' style="font-weight:bold;" ' end local goalscorerString = '\n*<span' .. styleString ..'>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon .. " " .. u['player'] -- name .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p bpgr5icx6a7x1unqcpr225tzkq51pi2 1361352 1361351 2019-01-22T13:48:47Z en>Jts1882 0 only bold the name 1361352 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "KOR" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end -- wikitext for bullet list --if playerActive then styleString = ' style="font-weight:bold;" ' end local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 1jnyod5ncjxwira047amgub2sn25sja 1361353 1361352 2019-01-22T14:27:55Z en>Jts1882 0 check for round/competiton complete 1361353 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "KOR" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p bxmy0bzz9ai1q3zpecmii3sf1tm9vgf 1361354 1361353 2019-01-22T15:04:43Z en>S.A. Julio 0 add 1361354 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p rrzp1qc2uchbb11nqe6dji4vo1j5ikx 1361355 1361354 2019-01-22T15:10:14Z en>S.A. Julio 0 add 1361355 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p ewn3mywgqve9uvcvhm2nnnq3t3gnepa 1361356 1361355 2019-01-23T07:46:19Z en>S.A. Julio 0 add 1361356 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p h7s55hdufvxht584mp17mivnl2png1p 1361357 1361356 2019-01-23T16:24:44Z en>S.A. Julio 0 add more special characters 1361357 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i"} } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p fqdzj2f7s7fmo9ewao53agx4wf6rmj8 1361358 1361357 2019-01-24T04:26:55Z en>S.A. Julio 0 add special characters 1361358 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p ofs2nxvnxjm6vml74gee1y4byvaktff 1361359 1361358 2019-01-25T12:11:14Z en>S.A. Julio 0 add special characters 1361359 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol, groupCol = 4, 3 -- first column for goals, default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == v[groupCol] then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p ppgvcpbis2ajhl6kfgx5xvqeoamo9gz 1361360 1361359 2019-01-27T17:25:07Z en>Jts1882 0 implement use of table of groups and countries (currently set in "UEFA Euro 2016 qualifying" data submodule; otherwise use column from goalscorers table) 1361360 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = 4 -- first column for goals --local groupCol = 3 -- default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get group from group table or from player table if the]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text) if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p eqayr20f3bmi88p1kt4mi077yri27f8 1361361 1361360 2019-01-27T18:11:28Z en>Jts1882 0 Display message about bolded player names if round/group selected not "complete" 1361361 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = 4 -- first column for goals --local groupCol = 3 -- default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get group from group table or from player table if the]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['bold'] or dateUpdated ~= "complete" then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p n5v8kdwfsdj3mxdiet4bwaiiecfcyu1 1361362 1361361 2019-01-29T13:56:26Z en>S.A. Julio 0 add template parameter 1361362 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = 4 -- first column for goals --local groupCol = 3 -- default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get group from group table or from player table if the]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] or dateUpdated ~= "complete" then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 71huf4rz8jkdrp8hd5iu3ugcm5hrxnn 1361363 1361362 2019-03-21T17:06:15Z en>S.A. Julio 0 hide for now 1361363 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = 4 -- first column for goals --local groupCol = 3 -- default column for group if round then goalsCol = data.rounds[round] or 4 -- get column containing goals for that round end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = 4, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get group from group table or from player table if the]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end -- if g.args['bold'] or dateUpdated ~= "complete" then -- text = text .. " Players highlighted in '''bold''' are still active in the competition." -- end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 110vz7x6go5o4x5incuycrfx82ux7tr 1361364 1361363 2019-03-22T08:34:21Z en>Jts1882 0 set first goalCol to first listed in data submodule rather than hardcoded 4 for all (in select goalscorers function) 1361364 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = 4 -- first column for goals --local groupCol = 3 -- default column for group if round then goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get group from group table or from player table if the]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end -- if g.args['bold'] or dateUpdated ~= "complete" then -- text = text .. " Players highlighted in '''bold''' are still active in the competition." -- end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 6w66esetj64q51o9yzo7xjme757xlsn 1361365 1361364 2019-03-22T08:55:06Z en>Jts1882 0 add function to get first goals column 1361365 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end -- if g.args['bold'] or dateUpdated ~= "complete" then -- text = text .. " Players highlighted in '''bold''' are still active in the competition." -- end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p f8jloen39avg0ktcaumohttdnu26vg7 1361366 1361365 2019-03-23T21:30:38Z en>S.A. Julio 0 add 1361366 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "THA", "VIE", "LAO" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end -- if g.args['bold'] or dateUpdated ~= "complete" then -- text = text .. " Players highlighted in '''bold''' are still active in the competition." -- end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p n2cktkiwfy583vgjll5jc6ktp1x5u93 1361367 1361366 2019-05-23T22:13:52Z en>S.A. Julio 0 remove 1361367 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end -- if g.args['bold'] or dateUpdated ~= "complete" then -- text = text .. " Players highlighted in '''bold''' are still active in the competition." -- end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p ozzec10mcg5oq57lqkzf0m1hn38j6e7 1361368 1361367 2019-06-11T11:01:42Z en>S.A. Julio 0 partially re-enable bold 1361368 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>" .. source .. "</small>" end return text .. output .. source end return p 84j5tuxg3o239p4pies5ll74i3gwjk1 1361369 1361368 2019-07-20T13:47:18Z en>Jts1882 0 modify source in template version 1361369 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then text = text .. " " .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p fv2gwwez63t79fvu47uhkec2pcsgsug 1361370 1361369 2019-07-20T16:38:40Z en>Jts1882 0 don't want space if nothing before further (this cause wrapping in pre tags) 1361370 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p q60jq354wk4sdhqldta33b39l0yuk9e 1361371 1361370 2019-09-05T20:48:55Z en>Anbans 585 0 Cambodian names are also in the East Asian name order 1361371 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p ov11il35h7hog1s6lukloqn6vhc12au 1361372 1361371 2019-10-04T09:57:25Z en>Jts1882 0 use bold parameter to override active players 1361372 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p g7ajtlo4cj45lpbp3sn4pehs1dg4mcj 1361373 1361372 2019-10-04T09:59:32Z en>Jts1882 0 remove sentence explain bold when bold=no 1361373 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p j8aacqyjtyechlwye5d6pdnxp7xxrzg 1361374 1361373 2019-10-04T10:31:45Z en>Jts1882 0 move goal total count outside minimum goal check 1361374 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "were" if ongoing then text1 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("There %s %d %ss scored%s.", text1, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p bucdhen9rcxiipgovtli0s99aixbxln 1361375 1361374 2019-10-06T08:41:31Z en>Jts1882 0 add parameter lc support for template parameter version 1361375 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s.", text2, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p 2c2xmy1wpj5fkpokx3bhonwp5u0cr75 1361376 1361375 2019-10-06T08:42:52Z en>Jts1882 0 missing parameter 1361376 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s.", text1, text2, statNumber, statType, averageString..updateString) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p 8xe23fdf0f7cjnoqtqbm8whyqato1bf 1361377 1361376 2019-10-06T10:14:39Z en>Jts1882 0 add separator parameter 1361377 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['update'] then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p hbt9wgvzikvwhnux2kadt6lj2ytpz6h 1361378 1361377 2019-10-07T09:15:44Z en>Jts1882 0 parameter 'updated' not 'update' 1361378 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" if g.args['goals'] and g.args['matches'] then averageString = string.format(", for an average of %.3g goals per match", g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p 3twzz5m9lmb5gno152tw1l6oab8l358 1361379 1361378 2019-10-07T09:42:13Z en>Jts1882 0 add in x matches for supplied parameter function 1361379 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p iutklgey94zxzwc5tua6f6ldkxif7ow 1361380 1361379 2019-10-09T17:59:48Z en>MusikBot II 0 Protected "[[Module:Goalscorers]]": [[Wikipedia:High-risk templates|High-risk template or module]] ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require autoconfirmed or confirmed access] (indefinite)) 1361379 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p iutklgey94zxzwc5tua6f6ldkxif7ow 1361381 1361380 2019-11-30T11:58:48Z en>Jts1882 0 add footer for template parameteres 1361381 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] local footerTitle = g.args['footer-title'] or g.args['bottom-text'] local footer = "" if footerText then local heading = "" if footerTitle then heading = '<div style="font-style:italic;" >' .. footerTitle .. '</div>' end footer = '<div style="font-size:85%;" >' .. heading .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. source end return p nmunqgwrxucnrkx4voyac4vlh4ci7w9 1361382 1361381 2019-11-30T12:01:23Z en>Jts1882 0 oops, must output it 1361382 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] local footer = "" if footerText then local heading = "" if footerHeading then heading = '<div style="font-style:italic;" >' .. footerHeading .. '</div>' end footer = '<div style="font-size:85%;" >' .. heading .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p hpu128mx5wu3ddvkbhebef1slk6v172 1361383 1361382 2019-11-30T12:39:05Z en>Jts1882 0 default values 1361383 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<div style="font-style:italic;" >' .. footerHeading .. '</div>' end footer = '<div style="font-size:85%;" >' .. heading .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p jpmaitk1vmkso4j1quz0pti2ovlginm 1361384 1361383 2019-11-30T13:02:05Z en>Jts1882 0 add columns 1361384 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<div style="font-style:italic;" >' .. footerHeading .. '</div>' end footer = '<div style="font-size:85%;padding-top:0.8em;" >' .. heading .. '<div class="div-col columns column-count column-count-3" style="{{column-count|3}}">' .. footerText .. '</div></div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 8v34zhui07v58z4ijw8aplcd3vulyka 1361385 1361384 2019-11-30T13:28:12Z en>Jts1882 0 simplify - leave formatting for wikitext 1361385 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' end number = number -1 end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p sowpv1vywzki1vzl69kb0tucihizdgi 1361386 1361385 2019-11-30T16:18:47Z en>Jts1882 0 add warning if template goals parameter and number of goals listed don't match 1361386 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if totalGoals ~= g.args['goals'] then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p sdffaoy1s8mdthhiekp2z8t72noucwz 1361387 1361386 2019-11-30T16:21:31Z en>Jts1882 0 match types for comparison 1361387 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p fiubu3tgn7ezy1fxc68qsh57r0ahzq5 1361388 1361387 2019-11-30T16:24:41Z en>Frietjes 0 1361388 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p qrnvh802xtvd6vmqy7h8saijgxm0ovl 1361389 1361388 2020-01-03T05:36:45Z en>Uzume 0 col-width for better accessibility, e.g., mobile browsers, etc. 1361389 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-width" style="' .. frame:expandTemplate{ title = 'column-width', args = {'20em'} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-width" style="{{column-width|20em}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-width" style="' .. frame:expandTemplate{ title = "column-width", args = {'20em'} } .. '">' .. "\n" .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-width" style="{{column-width|20em}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-width" style="' .. frame:expandTemplate{ title = "column-width", args = {'20em'} } .. '">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p gvxbza6b3tps2u5d6262yku5utzvpn9 1361390 1361389 2020-01-03T09:04:23Z en>S.A. Julio 0 unnecessary change 1361390 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p qrnvh802xtvd6vmqy7h8saijgxm0ovl 1361391 1361390 2020-12-16T23:54:12Z en>Izno 0 use templatestyles instead 1361391 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return frame:extensionTag{name = 'templatestyles', args = { src = 'Div col/styles.css' }} .. '<div class="div-col column-count" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. frame:extensionTag{name = 'templatestyles', args = { src = 'Div col/styles.css' }} .. '<div class="div-col column-count" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">\n' .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. frame:extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col column-count" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p rfii1ikbmh7nudjy41gcl0kcuv4lagz 1361392 1361391 2020-12-17T18:09:11Z en>Anbans 585 0 Undid revision 994680392 by [[Special:Contributions/Izno|Izno]] ([[User talk:Izno|talk]]) display which was available before the update. Now the default behaviour was coming out to have 2 columns instead of 3 columns (what already existed). Maybe it would be better to solve this test case before pushing the update 1361392 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p qrnvh802xtvd6vmqy7h8saijgxm0ovl 1361393 1361392 2021-01-09T21:15:44Z en>Plastikspork 0 Simplify, since {{column-count|3}} is the same as column-count:3; but we really should be using column-width instead for mobile! 1361393 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="column-count:3;">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="column-count:3;">' .. "\n" .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-count column-count-3" style="column-count:3;">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p crp22okxvx6h3ubysjr9irqedn6teox 1361394 1361393 2021-01-12T13:25:45Z en>Anbans 585 0 Undid revision 999373762 by [[Special:Contributions/Plastikspork|Plastikspork]] ([[User talk:Plastikspork|talk]]) The update is changing the style on the available pages. Somehow the sections are being defaulted to two column. This needs to be looked into before making the change. 1361394 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = 'column-count', args = {3} } .. '">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. "\n" .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="{{column-count|3}}"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-count column-count-3" style="' .. frame:expandTemplate{ title = "column-count", args = {3} } .. '">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p qrnvh802xtvd6vmqy7h8saijgxm0ovl 1361395 1361394 2021-01-12T15:12:12Z en>Plastikspork 0 Undid revision 999890310 by [[Special:Contributions/Anbans 585|Anbans 585]] ([[User talk:Anbans 585|talk]]) This changes nothing, all [[Template:Column-count]] does is prepend the text "column-count:" per talk page 1361395 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="column-count:3;">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="column-count:3;">' .. "\n" .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-count column-count-3" style="column-count:3;">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p crp22okxvx6h3ubysjr9irqedn6teox 1361396 1361395 2021-01-13T09:32:39Z en>Jts1882 0 use column width rather than column count 1361396 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="column-width:25em;">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. '<div class="div-col columns column-count column-count-3" style="column-width:25em;">' .. "\n" .. entry .. '</div>' totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. '<div class="div-col columns column-count column-count-3" style="column-width:25em;">' .. '\n' .. footerText .. '</div>' end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 4fb5lm86of61w2h75891m9n4v2ki85u 1361397 1361396 2021-01-13T12:51:57Z en>Jts1882 0 use openList() and closeList() in all cases (so formating handled in one place) 1361397 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="div-col columns column-count column-count-3" style="column-width:25em;">' end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p nkboq8ta8dy3fin76czh5sjlj4g971j 1361398 1361397 2021-01-13T13:03:56Z en>Jts1882 0 simplify classes in list 1361398 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="columns" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" if g.args['goals'] and tonumber(g.args['goals']) > 1 then text3 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text3,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %ss scored%s", text1, text2, statNumber, statType, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 1decjfmaow54xt5awqit4mvvoj5cfa0 1361399 1361398 2021-01-20T08:24:46Z en>Jts1882 0 fix plural texts for goal(s) and match(es) in introductory text for template parameter data 1361399 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="columns" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local text3 = "" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then text2 = "was" if ongoing then text2 = "has been" end else text3 = "s" end local text4 = "" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) > 1 then text4 = "es" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], text4,g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, text3, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p dy7uutgy26s94rafk8mmdp580ekhgnq 1361400 1361399 2021-01-20T13:01:08Z en>Jts1882 0 use more obvious parameter names 1361400 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="columns" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then averageString = string.format(" in %d match%s, for an average of %.3g goals per match", g.args['matches'], matchPlural, g.args['goals']/g.args['matches']) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p dbxjg4qqch5d4kqwy2hs46wsgqzheb1 1361401 1361400 2021-01-20T16:17:40Z en>Jts1882 0 fix average goal plural for template data function 1361401 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.outputGoalscorers(frame, og) -- output list of goalscorers local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="columns" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p qtvl0s2v75qc775ythftzmeiqsw5s8g 1361402 1361401 2021-02-08T10:33:57Z en>Jts1882 0 first pass at tabulated output (disabled) 1361402 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local rank = 0 local playerCount = 0 local rankCount = 0 local listOpen = false -- flag for list started by template {{Div Col}} local tableString = '\n{| class="wikitable"' ..'\n|-' .. '\n!Rank !! Player !! Goals' -- start table with headers for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- start new list/rowspan of new number of goals rank = rank + rankCount rankCount = 0 if rank > 10 then break end -- limit list top ten (TO DO use parameter) if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) tableString = tableString .. '\n|-\n|' .. rank .. '\n|' .. goalscorerString .. '\n|' .. u['goals'] end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) tableString = tableString .. "\n|}" return outputString .. tableString else return ("No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers --if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="columns" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 0rdsybvce8b2kpfuouzzbcs59ez0e2m 1361403 1361402 2021-02-18T12:32:38Z en>Jts1882 0 update from sandbox (alternative output as ranked table of goalscorers) 1361403 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return ("No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return '<div class="columns" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p q33s9tiemb7p1h2foufwtbhgkttegsc 1361404 1361403 2021-03-03T00:28:31Z en>Izno 0 re-implement div col tstyles here here, just ignore the column width style declaration which really isn't necessary but w/e (I don't care enough); this relieves the columns class 1361404 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### this section is currently unused will be used to take check parameters set in template ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### main() - simple output of the data in the module in list form ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 p.selectGoalscorers() -- selected goalscorers meeting round and group criteris -- CHANGEe: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local allGroupGames = 0 local latestGroupDate = "1800-01-01" if round == "all" or group == "all" then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end else matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end -- select players meeting round and goal criteria function p.selectGoalscorers(og) --data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum -- select all players with goals totals for appropriate rounds local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local goalsCol = p.getGoalsCol(round) -- 4 -- first column for goals --local groupCol = 3 -- default column for group if round then -- goalsCol = data.rounds[round] or data.rounds[1] or 4 -- get column containing goals for that round or first round listed if all end --groupCol = data.group[round] or 3 -- get column containing goals for that round -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- all rounds and goals --local i = 4 for i = goalsCol, #v, 1 do --or while i <= #v do goalsByRound, commentByRound = p.getGoals( v[i] , playerName) goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only --if group == v[groupCol] then -- single group only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end --return p.goalscorers -- it is available anyway end --[[ get column for round or first round listed if "all" -allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do return v; -- return the first one end end return data.rounds[round] or 4 -- get column containing goals for that round or first round listed if all end --[[ get group from group table or from player table ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return ("No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p jpzt1z7dn3ps6jqspinnafj5jdno1xw 1361405 1361404 2021-10-19T08:22:38Z en>Jts1882 0 update to sandbox version (see discussion at [[User talk:Centaur271188]] 1361405 Scribunto text/plain require('Module:No globals'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return ("No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p hm6rueg8ouretpjto5wtc7uyh8j17pb 1361406 1361405 2022-10-21T19:47:06Z en>WOSlinker 0 use require('strict') instead of require('Module:No globals') 1361406 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return ("No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 6mcpeut3w64pveaf6zeu6vh7i6cayo2 1361407 1361406 2022-12-14T17:28:27Z en>Frietjes 0 remove newlines at top? 1361407 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return ("No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end output = mw.ustring.replace(output, '^[\n][\n]*', '') return text .. output .. footer .. source end return p dnl3w1nltoa85fa6op2q8wztyhz0oh2 1361408 1361407 2022-12-14T17:28:55Z en>Frietjes 0 1361408 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return ("No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end output = mw.ustring.gsub(output, '^[\n][\n]*', '') return text .. output .. footer .. source end return p p41fiz7v09yan5cyx51uq4h4pmi69a5 1361409 1361408 2022-12-14T18:44:01Z en>Spike 'em 0 Restored revision 1117447587 by [[Special:Contributions/WOSlinker|WOSlinker]] ([[User talk:WOSlinker|talk]]): Think this has caused unexpected behaviour 1361409 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return ("No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 6mcpeut3w64pveaf6zeu6vh7i6cayo2 1361410 1361409 2024-03-22T22:22:33Z en>Jkudlick 0 adding whitespace to output when 0 goals have been scored 1361410 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 8s3r71lwqtc2gav2wiqyg6p04gm1hvq 1361411 1361410 2024-03-22T22:32:03Z en>Jkudlick 0 whitespace at end of header sentence 1361411 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. ".&nbsp;" else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ").&nbsp;" end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 397r5wduoupciiewwnr2wyxcmlz1wu8 1361412 1361411 2024-03-22T23:19:34Z en>Jkudlick 0 Undid revision [[Special:Diff/1215068481|1215068481]] by [[Special:Contributions/Jkudlick|Jkudlick]] ([[User talk:Jkudlick|talk]]) self-rv; extra whitespace added when bold=yes 1361412 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return ("No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 8s3r71lwqtc2gav2wiqyg6p04gm1hvq 1361413 1361412 2024-03-22T23:23:29Z en>Jkudlick 0 leading whitespace for this sentence 1361413 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p seuj52xwl2uobgz0p9bxpv9cj2u3yik 1361414 1361413 2024-09-27T15:23:40Z en>AnvarxonM 0 1361414 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' ta avtogol'] or g.args[math.abs(number) .. ' ta avtogol'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p l1ocsdnhnms6asxgj6mh4lybb7615am 1361415 1361414 2024-09-27T15:24:06Z en>AnvarxonM 0 Undid revision [[Special:Diff/1248087017|1248087017]] by [[Special:Contributions/AnvarxonM|AnvarxonM]] ([[User talk:AnvarxonM|talk]]) 1361415 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p seuj52xwl2uobgz0p9bxpv9cj2u3yik 1361416 1361415 2024-10-16T10:27:12Z en>Jts1882 0 add fix for case where all goalscorers have one goal (see talk page question) 1361416 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = g.args['goals'] or g.args['assists'] or 0 local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %d %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p ep75jjv9lwj90drsfowv1pkrc76towc 1361417 1361416 2024-10-16T11:50:48Z en>Jts1882 0 format number as string in template parameter version (e.g. 2,452 goals) 1361417 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or g.args['assists'] or 0) ) --format number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p p1mjjv0of1azc6c3ad02wmfs04e2lrx 1361418 1361417 2024-10-27T09:10:31Z en>Jts1882 0 statNumber in useTemplateData() only needed for goals (assists is a flag) 1361418 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort funtion ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p e7qpfkfqu7e9egpjs6idnztmszyave3 1361419 1361418 2024-12-18T20:40:23Z en>Shonebrooks 0 I corrected the spelling of "function." [[WP:TYPO]] 1361419 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p iod8vfu16a8xe3td6ru694ko8u8w6j5 1361420 1361419 2025-02-21T18:01:19Z en>MusikBot II 0 Changed protection settings for "[[Module:Goalscorers]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 2501 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require extended confirmed access] (indefinite) [Move=Require extended confirmed access] (indefinite)) 1361419 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p iod8vfu16a8xe3td6ru694ko8u8w6j5 1361421 1361420 2025-03-23T23:51:40Z en>Jkudlick 0 fixing error where last goalscorers in table are repeated if on one goal 1361421 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rank == 1 then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 33ebv7nnm7cypd3xqryephyyqptcfgt 1361422 1361421 2025-03-24T01:37:08Z en>Jkudlick 0 build 1 goal table if rank <= maxRank; weird error where not displaying at rank = 3 1361422 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rank <= maxRank then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 5u8yj6k606h78v0mwrbz0ikqt2d02un 1361423 1361422 2025-03-27T18:15:26Z en>Jts1882 0 test for issue on module talk page 1361423 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 or (rankCount >10 )then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals local test = "" if rankCount > 10 then test ="ten" end playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString .. test -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rankCount > 10 then firstplayerCell = "\n|''" .. rankCount .. " players''" playerCells = "" --goalNumber rankCount = 0 end if goalNumber == 1 and rank <= maxRank then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 804vn4vfxx44dust443ometbcdzhpzg 1361424 1361423 2025-03-27T18:16:01Z en>Jts1882 0 undo test until further testing 1361424 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rank <= maxRank then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 5u8yj6k606h78v0mwrbz0ikqt2d02un 1361425 1361424 2025-04-06T17:00:42Z en>Jts1882 0 temporary test edit (see talk page) 1361425 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rankCount >= (10-1) then -- special case: long list of goalscorers with one goal; don't show if more than 10 players firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. (rankCount+1) .. " players" -- replace list with "x players" text playerCells = "" -- clear multirow list of players on one goal rankCount = 0 -- reset to get single rowspan in next section end if goalNumber == 1 and rank <= maxRank then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p ljl8m8ldyilmkpb6oxkwht29mjdwhwg 1361426 1361425 2025-04-06T17:01:31Z en>Jts1882 0 Undid revision [[Special:Diff/1284281081|1284281081]] by [[Special:Contributions/Jts1882|Jts1882]] ([[User talk:Jts1882|talk]]) revert test for now 1361426 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "d" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rank <= maxRank then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p 5u8yj6k606h78v0mwrbz0ikqt2d02un 1361427 1361426 2026-05-13T16:55:27Z en>S.A. Julio 0 add to special characters 1361427 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "dj" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } , { "ō", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rank <= maxRank then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p m4b1zugszwgn63ioqeo52f51hm0wo98 1361428 1361427 2026-05-13T17:09:12Z en>S.A. Julio 0 add another to special characters 1361428 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "dj" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } , { "ō", "o" } , { "î", "i" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rank <= maxRank then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p a1ldfvfp4cngc6109bwy663kkb7xyt9 1361429 1361428 2026-05-18T11:36:14Z en>S.A. Julio 0 add 1361429 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "dj" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } , { "ō", "o" } , { "î", "i" }, { "õ", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rank <= maxRank then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local level = data.templates['youth_level'] or "" -- parameter for youth level, ie under-21 -- equivalent to {{fbicon|country}} local flagVariant = "" if data.templates.flagvar and data.templates.flagvar[country] then flagVariant = data.templates.flagvar[country] end if level ~= "" then return frame:expandTemplate{ title = icon , args = { level, country, flagVariant } } else return frame:expandTemplate{ title = icon , args = { country, flagVariant } } -- flag icon end end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end return p f1xkebxtcup4irt8g7zkdoyjnrrwbcu 1361430 1361429 2026-06-03T07:22:03Z en>S.A. Julio 0 adding features to output individual number of goals, matches played, top scorer, update date. now allows for specifying number of matches finished on a given day. also uses Module:Flagg to reduce the post-expand include size 1361430 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end --[[ ##################### standalone value outputs ########################## p.goals(frame) - output ONLY the total number of goals scored p.matches(frame) - output ONLY the number of matches played p.date(frame) - output ONLY the date of the most recent matches played accepts optional |format=yes to comma-format the number (e.g. 1,234). ]] function p.goals(frame) getArgs(frame) local result local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/' .. dataTarget) g.goalscorers = {} -- reset state (safe for multiple invokes per page) g.totalGoals = 0 local ok = p.selectGoalscorers() -- count goals for selected round/group if not ok then return p.error_msg() end p.selectGoalscorers("OG") -- include own goals in the total if p.errorString ~= "" then return p.error_msg() end result = g.totalGoals else result = tonumber(g.args['goals']) or 0 -- fall back to template-supplied data end if yesno(g.args['format']) then return mw.getLanguage('en'):formatNum(result) end return tostring(result) end function p.matches(frame) getArgs(frame) local result local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/' .. dataTarget) local round = g.args['round'] or "all" if round ~= "all" and not p.validateRound(round) then -- guard against bad round p.errorString = p.errorString .. 'Invalid round "' .. round .. '" specified. ' return p.error_msg() end result = p.getNumberMatches() -- respects round/group args else result = tonumber(g.args['matches']) or 0 end if yesno(g.args['format']) then return mw.getLanguage('en'):formatNum(result) end return tostring(result) end function p.date(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if not dataTarget then return g.args['updated'] or "" end -- template-data fallback data = require('Module:Goalscorers/data/' .. dataTarget) local round = g.args['round'] or "all" if round ~= "all" and not p.validateRound(round) then p.errorString = p.errorString .. 'Invalid round "' .. round .. '" specified. ' return p.error_msg() end local _, dateUpdated = p.getNumberMatches() if dateUpdated == "complete" or dateUpdated == "" then return "" end -- nothing to show local dateFormat = (data.params and data.params['date_format']) or 'dmy' local mdy = yesno(g.args['mdy']) if mdy == true then dateFormat = "mdy" elseif mdy == false then dateFormat = "dmy" end local r, grp = p.getRoundAndGroup() local finished = p.matchesFinished(r, grp, dateUpdated) if finished ~= "" then finished = " (" .. finished .. ")" end return p.error_msg() or (require('Module:Date')._Date(dateUpdated):text(dateFormat) .. finished) end --[[ ##################### matches-finished helper ############################ p.matchesFinished(round, group, latestDate) Sums the optional "F/T" field (3rd element of a data.updated entry) for every entry dated on latestDate. Older dates are ignored. Returns "" when no entry supplies F/T, or a contributing entry on that date lacks it. ]] function p.matchesFinished(round, group, latestDate) if not latestDate or latestDate == "complete" or latestDate == "" or latestDate == "1700-01-01" then return "" end local entries = {} -- entries applying to round/group if round == "all" then for k, v in pairs(data.updated) do if k ~= "date" and k ~= "group" and p.validateRound(k) then entries[#entries+1] = v end end elseif round ~= "group" then entries[#entries+1] = data.updated[round] end if (round == "all" or round == "group") and data.updated.group then if group and group ~= "all" then entries[#entries+1] = data.updated.group[group] else for _, v in pairs(data.updated.group) do entries[#entries+1] = v end end end local finished, total, found = 0, 0, false -- sum F/T on the most-recent date for _, e in ipairs(entries) do if e[2] == latestDate then local f, t = string.match(tostring(e[3] or ""), "^%s*(%d+)%s*/%s*(%d+)%s*$") if not f then return "" end -- contributing entry without F/T -> skip finished, total, found = finished + f, total + t, true end end if not found then return "" end if finished >= total or finished < 1 or total < 1 then return "" end -- all done / invalid -> date only return finished .. " of " .. total .. " matches finished" end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end local round, group = p.getRoundAndGroup() local finished = p.matchesFinished(round, group, dateUpdated) if finished ~= "" then finished = ", " .. finished end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. finished .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "dj" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } , { "ō", "o" } , { "î", "i" }, { "õ", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rank <= maxRank then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) g.iconCache = g.iconCache or {} local cache = g.iconCache[data] -- per data module (safe across invokes) if not cache then cache = {}; g.iconCache[data] = cache end if cache[country] ~= nil then return cache[country] end -- already built for this team local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local flagVariant = data.templates.flagvar and data.templates.flagvar[country] local result if icon == 'fbicon' then -- {{#invoke:flagg|main|pxxl|avar=fb|variant=VAR|CODE}} local args = { 'pxxl', country, avar = 'fb' } if flagVariant then args.variant = flagVariant end result = require('Module:Flagg').main(frame:newChild{ args = args }) else local level = data.templates['youth_level'] or "" -- youth level, e.g. under-21 if level ~= "" then result = frame:expandTemplate{ title = icon, args = { level, country, flagVariant or "" } } else result = frame:expandTemplate{ title = icon, args = { country, flagVariant or "" } } end end cache[country] = result return result end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end --[[ ######################## top scorer output ############################### p.topscorer(frame) - output the top goalscorer(s) for the whole competition |maxlist= how many tied players to list before collapsing to generic "N players" text (default 5) |basepage= page used in the collapsed link (default: current page) |section= section anchor for that link (default: Goalscorers) ]] function p.topscorer(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if not dataTarget then return "" end -- this feature needs module data data = require('Module:Goalscorers/data/' .. dataTarget) g.goalscorers = {} -- reset state (safe across invokes) g.totalGoals = 0 local ok = p.selectGoalscorers() -- regular goals only; own goals ignored if not ok then return p.error_msg() end p.sortGoalscorers() -- sorts by goals desc, then country, name if #g.goalscorers == 0 then return "" end -- no scorers -> output nothing -- collect the tied leaders (sorted, so they sit at the front of the list) local topGoals = g.goalscorers[1].goals local leaders = {} for _, v in ipairs(g.goalscorers) do if v.goals == topGoals then leaders[#leaders + 1] = v else break end end local numTied = #leaders local maxList = tonumber(g.args['maxlist']) or 5 local goalWord = (topGoals == 1) and "goal" or "goals" local output if numTied == 1 then -- single top scorer local v = leaders[1] output = p.addLinkedIcon(frame, v.country) .. " " .. v.player .. ' <span class="nowrap">(' .. topGoals .. ' ' .. goalWord .. ')</span>' elseif numTied <= maxList then -- list each tied player local mList = require('Module:List') local listArgs = { class = 'nowrap' } for _, v in ipairs(leaders) do listArgs[#listArgs + 1] = p.addLinkedIcon(frame, v.country) .. " " .. v.player end listArgs[#listArgs + 1] = '(' .. topGoals .. ' ' .. goalWord .. ' each)' output = mList.makeList('unbulleted', listArgs) else -- too many tied -> generic text local mList = require('Module:List') local cn = require('Module:ConvertNumeric') local writtenNum = cn.spell_number2{ num = numTied, capitalize = true } -- e.g. 7 -> "Seven" local basePage = g.args['basepage'] or mw.title.getCurrentTitle().text local section = g.args['section'] or 'Goalscorers' output = mList.makeList('unbulleted', { class = 'nowrap', "''[[" .. basePage .. "#" .. section .. "|" .. writtenNum .. " players]]''", '(' .. topGoals .. ' ' .. goalWord .. ' each)' }) end return p.error_msg() or output end return p r75cn9j2fxjrzn8x5ruc033d3cuei99 1361431 1361430 2026-06-12T08:16:03Z पर्वत सुवेदी 31224 [[:en:Module:Goalscorers]] बाट २२७ संशोधन(हरू): आयात गर्दै 1361430 Scribunto text/plain require('strict'); local yesno = require('Module:Yesno') local p = {} local g = {} -- for parameters with global scope in this module g.goalscorers = {} -- table where selected and sorted players will be place g.args = {} g.totalGoals = 0 local data = {} -- module subpage data -- require('Module:Goalscorers/data/UEFA Euro 2016 qualifying'); p.errorString = "" function p.error_msg() if p.errorString ~= "" then return '<span style="font-size:100%" class="error">' -- '<code style="color:inherit;border:inherit;padding:inherit;">&#124;_template=</code>' .. p.errorString .. '</span>'; end end -- data for goals scored held in module subpages, e.g. "Module:Goalscorers/data/UEFA Euro 2016 qualifying" --[[ parameters containing data help in three tables data.rounds = {} -- group, play-off data.goalscorers = {} -- player, country, goals in each round) data.owngoalscorers = {} -- player, country, goals in each round) data.updated = {} -- date of latest update (month, day, year) --]] --[[ ############################ Parameter handing ############################### p.getArgs() - gets arguments from frame (invoke) or parent frame (template) ]] local function getArgs(frame) local parents = mw.getCurrentFrame():getParent() for k,v in pairs(parents.args) do --check content if v and v ~= "" then g.args[k]=mw.text.trim(v) --parents.args[k] end end for k,v in pairs(frame.args) do --check content if v and v ~= "" then g.args[k]= mw.text.trim(v) --parents.args[k] end end -- allow empty caption to blank default --if parents.args['caption'] then templateArgs['caption'] = parents.args['caption'] end end --[[ ############################## Main function and other functions ###################### p.main() - simple output of the data in the module in list form p.addIntroductorySentence() - add sentence on number of goals and matches, with goals per match p.addFooterSentence() - add footnote p.getNumberMatches() p.owngoals() - get own goals (no longer used?) p._owngoals() - core functionality for p.owngoals() ]] function p.main(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/'.. dataTarget) --or 'UEFA Euro 2016 qualifying' return p.useModuleData(frame) -- data on goals taken from module subpage else return p.useTemplateData(frame) -- data on goals/assists taken from template end end function p.useModuleData(frame) --p.goalscorers = {} -- table where selected and sorted players will be place g.totalGoals = 0 local ok = p.selectGoalscorers() -- selected goalscorers meeting round and group criteris if not ok then return p.error_msg() end -- CHANGE: append own goals to list (data will now include goals and own goals (negative)) p.selectGoalscorers("OG") p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country local outputString = p.addIntroductorySentence() .. p.outputGoalscorers(frame) .. p.addFooterSentence() -- .. "" --TODO add intermediate heading? -- .. p._owngoals(frame) -- output list of goalscorers return p.error_msg() or outputString end --[[ ##################### standalone value outputs ########################## p.goals(frame) - output ONLY the total number of goals scored p.matches(frame) - output ONLY the number of matches played p.date(frame) - output ONLY the date of the most recent matches played accepts optional |format=yes to comma-format the number (e.g. 1,234). ]] function p.goals(frame) getArgs(frame) local result local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/' .. dataTarget) g.goalscorers = {} -- reset state (safe for multiple invokes per page) g.totalGoals = 0 local ok = p.selectGoalscorers() -- count goals for selected round/group if not ok then return p.error_msg() end p.selectGoalscorers("OG") -- include own goals in the total if p.errorString ~= "" then return p.error_msg() end result = g.totalGoals else result = tonumber(g.args['goals']) or 0 -- fall back to template-supplied data end if yesno(g.args['format']) then return mw.getLanguage('en'):formatNum(result) end return tostring(result) end function p.matches(frame) getArgs(frame) local result local dataTarget = g.args[1] or g.args['data'] if dataTarget then data = require('Module:Goalscorers/data/' .. dataTarget) local round = g.args['round'] or "all" if round ~= "all" and not p.validateRound(round) then -- guard against bad round p.errorString = p.errorString .. 'Invalid round "' .. round .. '" specified. ' return p.error_msg() end result = p.getNumberMatches() -- respects round/group args else result = tonumber(g.args['matches']) or 0 end if yesno(g.args['format']) then return mw.getLanguage('en'):formatNum(result) end return tostring(result) end function p.date(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if not dataTarget then return g.args['updated'] or "" end -- template-data fallback data = require('Module:Goalscorers/data/' .. dataTarget) local round = g.args['round'] or "all" if round ~= "all" and not p.validateRound(round) then p.errorString = p.errorString .. 'Invalid round "' .. round .. '" specified. ' return p.error_msg() end local _, dateUpdated = p.getNumberMatches() if dateUpdated == "complete" or dateUpdated == "" then return "" end -- nothing to show local dateFormat = (data.params and data.params['date_format']) or 'dmy' local mdy = yesno(g.args['mdy']) if mdy == true then dateFormat = "mdy" elseif mdy == false then dateFormat = "dmy" end local r, grp = p.getRoundAndGroup() local finished = p.matchesFinished(r, grp, dateUpdated) if finished ~= "" then finished = " (" .. finished .. ")" end return p.error_msg() or (require('Module:Date')._Date(dateUpdated):text(dateFormat) .. finished) end --[[ ##################### matches-finished helper ############################ p.matchesFinished(round, group, latestDate) Sums the optional "F/T" field (3rd element of a data.updated entry) for every entry dated on latestDate. Older dates are ignored. Returns "" when no entry supplies F/T, or a contributing entry on that date lacks it. ]] function p.matchesFinished(round, group, latestDate) if not latestDate or latestDate == "complete" or latestDate == "" or latestDate == "1700-01-01" then return "" end local entries = {} -- entries applying to round/group if round == "all" then for k, v in pairs(data.updated) do if k ~= "date" and k ~= "group" and p.validateRound(k) then entries[#entries+1] = v end end elseif round ~= "group" then entries[#entries+1] = data.updated[round] end if (round == "all" or round == "group") and data.updated.group then if group and group ~= "all" then entries[#entries+1] = data.updated.group[group] else for _, v in pairs(data.updated.group) do entries[#entries+1] = v end end end local finished, total, found = 0, 0, false -- sum F/T on the most-recent date for _, e in ipairs(entries) do if e[2] == latestDate then local f, t = string.match(tostring(e[3] or ""), "^%s*(%d+)%s*/%s*(%d+)%s*$") if not f then return "" end -- contributing entry without F/T -> skip finished, total, found = finished + f, total + t, true end end if not found then return "" end if finished >= total or finished < 1 or total < 1 then return "" end -- all done / invalid -> date only return finished .. " of " .. total .. " matches finished" end function p.addIntroductorySentence() -- add introductory text local totalGoalString = "A total of " .. g.totalGoals .. " goals were scored." --There were [has been|have been|was|were] #GOALS goal(s) scored in #MATCHES match(s), for an average of #GOALS/#MATCHES per match. local matches, dateUpdated = p.getNumberMatches() local mdyFormat = yesno(g.args['mdy']) local Date = require('Module:Date')._Date local pluralGoals = "s" local text1 = "" if g.totalGoals == 1 then pluralGoals = "" if dateUpdated == 'complete' then text1 = "was" else text1 = "has been" end else if dateUpdated == 'complete' then text1 = "were" else text1 = "have been" end end local text = string.format("There %s %s goal%s scored", text1, mw.getLanguage('en'):formatNum(g.totalGoals), pluralGoals) local pluralMatches = "es" if matches==1 then pluralMatches = "" end if matches then local average = g.totalGoals/tonumber(matches) local precision = 3 -- display d.dd (three significant disgits) if average < 1 then precision = 2 end -- display 0.dd (thwo significant disgits) average = tostring (average) local pluralAverage = "s" if tonumber(string.format("%.2f",average))==1 then pluralAverage = "" end text = text .. string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) end if dateUpdated == 'complete' or dateUpdated == "" then text = text .. "." else local dateFormat = 'dmy' -- default if data.params and data.params['date_format'] then dateFormat = data.params['date_format'] end -- from data module if mdyFormat == true then dateFormat = "mdy" else if mdyFormat == false then dateFormat = "dmy" end -- template param overrides end local round, group = p.getRoundAndGroup() local finished = p.matchesFinished(round, group, dateUpdated) if finished ~= "" then finished = ", " .. finished end text = text .. " (as of " .. Date(dateUpdated):text(dateFormat) .. finished .. ")." end text = p.addAdditionHeaderText(text, dateUpdated) -- handles template parameters bold, further, extra return text --totalGoalString end function p.addFooterSentence() -- add notes at bottom local footerSentence = g.args['footer'] or "" --footerSentence = "This is a footer sentence." -- test footer if data.params then local footer = data.params['footer'] or nil if footer then local frame = mw.getCurrentFrame() local processed = frame:preprocess(footer) if g.notes then footerSentence = footerSentence .. processed end end end if footerSentence ~= "" then footerSentence = '<div style = "" >' .. footerSentence .. '</div>' end return footerSentence end function p.getNumberMatches() local matches = g.args['matches'] local dateUpdated = data.updated['date'] or "1700-01-01" --'complete' -- assume completed if missing --local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs --local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local round, group = p.getRoundAndGroup() local allGroupGames = 0 local latestGroupDate = "1800-01-01" if group and (round == "all" or group == "all") then -- count all the group games for k,v in pairs(data.updated.group) do allGroupGames = allGroupGames + v[1] if v[2] ~= "complete" and v[2] > latestGroupDate then latestGroupDate = v[2] end -- update if later date end if latestGroupDate == "1800-01-01" then latestGroupDate = "complete" end -- no dates so must be complete end if group and (round == "all" and group ~= "all") then -- for totals of all rounds with only one group allGroupGames = data.updated.group[group][1] -- number matches latestGroupDate = data.updated.group[group][2] -- update date or completed end if round == "all" then -- all rounds and goals matches=0 for k,v in pairs(data.updated) do if k == "group" then matches = matches + allGroupGames if latestGroupDate ~= "complete" and latestGroupDate > dateUpdated then dateUpdated = latestGroupDate -- update if later date end elseif p.validateRound(k) then matches = matches + v[1] if v[2] ~= "complete" and v[2] > dateUpdated then dateUpdated = v[2] end -- update if later date end end elseif round == "group" then -- group round only if group == "all" then matches = allGroupGames dateUpdated = latestGroupDate else -- single group only matches = data.updated.group[group][1] -- number matches dateUpdated = data.updated.group[group][2] -- update date or completed end else -- any other round matches = data.updated[round][1] -- number matches dateUpdated = data.updated[round][2] -- update date or completed end if dateUpdated == "1700-01-01" then dateUpdated = "complete" end -- no dates so must be complete return matches, dateUpdated end function p.owngoals(frame) -- need to check parameters if external call getArgs(frame) data = require('Module:Goalscorers/data/'.. g.args[1]) --or 'UEFA Euro 2016 qualifying' local outputString = p._owngoals(frame) return p.error_msg() or outputString end function p._owngoals(frame) -- internal call for own goals --p.goalscorers = {} -- table where selected and sorted players will be place p.selectGoalscorers("OG") -- selected goalscorers meeting round and group criteris p.sortGoalscorers() -- sort selected goalscorers by number of goal, then country return p.outputGoalscorers(frame, "OG") -- output list of goalscorers end function p.validateRound(round) local validateRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists end return validateRound end --[[ ############################## functions to select goalscorers ###################### p.selectGoalscorers() - select goals scoreers required for list (rounds, groups) p.getRoundAndGroup() p.getGoalsCol(round) - get column containing round data or first data column if round = all (country, possibleGroup) p.getGoals (u, player) p.parseComment(comment) p.getPlayer(u) ]] --[[ p.selectGoalscorers() - select players meeting round and group criteria from goalscoreres list - gets goals and comments ]] function p.selectGoalscorers(og) local round, group = p.getRoundAndGroup() if not round then return false end -- exit if no valid round local goalMinimum = tonumber(g.args['minimum']) or -5 -- assume 5 own goals is maximum local goalsCol = p.getGoalsCol(round) -- first column for goals -- select players who have scored in rounds/groups requested local goalscorerData = data.goalscorers if og == "OG" then goalscorerData = data.owngoalscorers end for k,v in pairs(goalscorerData) do local goals, comment = 0, "" -- goals > 0 is the flag to include the player local playerName, playerAlias = p.getPlayer(v[1]) -- player name local goalsByRound, commentByRound = 0, "" if round == "all" then -- goals in all rounds and all groups for i = goalsCol, #v, 1 do if group and group ~= "all" and i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound --TODO use getGoals on round options if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "all2" and group ~= "all" then -- goals in all rounds but only from one group --TODO code to go through all rounds but only include goals in specified group [TODO merge with above option] --mw.addWarning( g.args[1] .. ":Mix:round=all and group=" .. group .. "/" .. p.getGroup(v[2], v[3] ) ) for i = goalsCol, #v, 1 do if i == p.getGoalsCol("group") and group ~= p.getGroup(v[2], v[3]) then goalsByRound = 0 commentByRound = "" else goalsByRound, commentByRound = p.getGoals( v[i] , playerName) end goals = goals + goalsByRound if commentByRound ~= "" then if comment == "" then comment = commentByRound else comment = comment .. "," .. commentByRound --TODO decide on comma or semi-colon end end i = i+1 end elseif round == "group" then -- group round only if group == p.getGroup(v[2], v[3]) then -- single group only goals, comment = p.getGoals( v[goalsCol] , playerName) elseif group == "all" then -- any group goals, comment = p.getGoals( v[goalsCol] , playerName) else -- do nothing for other groups end --elseif round == "playoffs" then -- playoff round (redunant?) -- goals = v[goalsCol] else -- any other round goals, comment = p.getGoals( v[goalsCol] , playerName) -- should also handle playoffs end if goals >= goalMinimum and goals ~= 0 then if comment ~= "" then if og == "OG" then comment = '<span> (' .. p.sortComment(comment) .. ')</span>' else comment = '<span>' .. comment .. '</span>' -- no parenthesis when using notes end end if og == "OG" then goals = -goals end -- make owngoals negative numbers g.goalscorers[#g.goalscorers+1] = { player=playerName, alias=playerAlias, country=v[2], goals=goals, comment=p.parseComment(comment)} --g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end g.totalGoals = g.totalGoals + math.abs(goals) -- increment total goal counter end return true -- data collected for selected goalscorers end --[[ p.getRoundAndGroup() ]] function p.getRoundAndGroup() local round = g.args['round'] or "all" -- round = all(empty)|group|playoffs local group = g.args['group'] or "all" -- group = all(empty), A,B,C etc local validateRound = false local validateGroupRound = false for k,v in pairs(data.rounds) do if k == round then validateRound = true end -- data for this round exists if k == "group" then validateGroupRound = true end -- there is a group round end if validateRound == false and round ~= "all" then local message = 'Invalid round "' .. round .. '" specified. No data found for that round. ' mw.addWarning( message ) p.errorString = p.errorString .. message round = nil end if validateGroupRound == false then group = false end -- there is no group round -- TODO add group error checking -- Could merge with getGoalsCol() and also return goalsCol return round, group end --[[ p.getGoalsCol(round) - get column containing round data or first data column if round = "all" - allows group column to be omitted from player table when group table provided ]] function p.getGoalsCol(round) local minimum = 1000 if round == "all" then -- if all need column of first round for k,v in pairs(data.rounds) do if v < minimum then minimum = v end --return v -- return the first one [this seemed to work reliably, but sometimes table order is not as listed] end return minimum end if data.rounds and data.rounds[round] then return data.rounds[round] -- get column containing goals for that round else return 4 -- an old default when no data.round (may not be necessary) end end --[[ p.getGroup(country, possibleGroup) - get group from group table or from player table - possibleGroup is the column containing the Group (when no group table) or the first data column ]] function p.getGroup(country, possibleGroup) -- row contain player name, country code, group if given, goals if data.groups then for k,v in pairs(data.groups) do -- iterate through the groups --local = gotGroup = false for j,u in pairs(v) do -- for each group if u == country then return k end end end return "no group found" else return possibleGroup -- no group table, so assume column three contains the group end end --[[ get number of goals and any associated comment the goals can be a single number (the usual case) or as an option table (e.g. for own goals): { number of own goals, comma-delimited list of opponents } - if the entry is a table, we want the first entry (a number) and the second (comment string) - otherwise, if a number, we just want the number and an empty string ]] function p.getGoals (u, player) if type(u) == 'table' and type(u[1]) == 'number' then return u[1], u[2] -- return number of goals, comment elseif type(u) == 'number' then return u, "" -- return number of goals, empty string else p.errorString = p.errorString .. " Invalid goals entry for player " .. player return 0, "" end end function p.parseComment(comment) local frame = mw.getCurrentFrame() -- we have something like "{{efn-ua|name=goals}}" if string.find(comment, "efn" , 1 , true ) then -- if we have a comment with a note g.notes = true -- set flag end return frame:preprocess(comment) end function p.getPlayer(u) if type(u) == 'table' then if type(u[1]) == 'string' and type(u[2]) == 'string' then --[[if #u[2] >1 then p.errorString = p.errorString .. "\n\nWe have u[1]=" .. u[1] .. " and u[2]=" .. u[2] end]] return u[1], u[2] -- return player name, player sorting alias else p.errorString = p.errorString .. " Invalid name entry for player " .. u[1] .. ", " .. u[2] return "", "" --TODO errroer end elseif type(u) == 'string' then return u, "" -- return player name else p.errorString = p.errorString .. " Invalid name entry for player " .. u or u[1] or "unknown" return "", "" end end --[[ ############################## functions to sort goalscorers ###################### p.preprocessSortName (name) p.getPlayerSortName (playerName, sortName, countryName) p.sortComment(comment) p.getCountryName(country) p.sortGoalscorers() -- the main sort function ]] --[=[ function p.preprocessSortName() stripp off wikitext [[ and ]] force to lowercase change special characters to standard letters ]=] function p.preprocessSortName (name) name = string.gsub(name, "%[%[", "") -- strip off [[ and ]] name = string.gsub(name, "%]%]", "") --name =string.lower(name) -- force lower case and return name = mw.ustring.lower(name) -- use unicode function local specialChars = { -- list of special characters and replacement pairs { "ı", "i" } , { "İ", "i" } , { "ß", "ss" }, { "ý", "y" } , { "ř", "r" } , { "ő", "o" }, { "é", "e" } , { "è", "e" } , { "þ", "th" }, { "ē", "e" } , { "ņ", "n" } , { "č", "c" }, { "ū", "u" } , { "ž", "z" } , { "æ", "ae" }, { "å", "a" } , { "ø", "o" } , { "ą", "a" }, { "ń", "n" } , { "ł", "l" } , { "ã", "a" }, { "ș", "s" } , { "š", "s" } , { "í", "i" }, { "á", "a" } , { "ä", "a" } , { "ć", "c" }, { "ç", "c" } , { "ğ", "g" } , { "ö", "o" }, { "ë", "e" } , { "ú", "u" } , { "ó", "o" }, { "ð", "d" } , { "ü", "u" } , { "ű", "u" }, { "ā", "a" } , { "ī", "i" } , { "đ", "dj" }, { "ă", "a" } , { "â", "a" } , { "ż", "z" }, { "ț", "t" } , { "ş", "s" } , { "ś", "s" }, { "ǎ", "a" } , { "ě", "e" } , { "ů", "u" }, { "ĕ", "e" } , { "ñ", "n" } , { "ď", "d" }, { "ï", "i" } , { "ź", "z" } , { "ô", "o" }, { "ė", "e" } , { "ľ", "l" } , { "ģ", "g" }, { "ļ", "l" } , { "ę", "e" } , { "ň", "n" }, { "ò", "o" } , { "ō", "o" } , { "î", "i" }, { "õ", "o" } } for k,v in pairs(specialChars) do -- replace special characters from supplied list name = string.gsub(name, v[1], v[2]) end return name end --[[ return the name for sorting return supplied alias name for sorting otherwise checks for pipe (redirect) and uses name after pipe splits name into words returns first name if only name (e.g. Nani) otherwise returns name in format second_name [.. last name], firstname ]] function p.getPlayerSortName (playerName, sortName, countryName) --dewikify all names before sorting, also forces lowercase playerName = p.preprocessSortName(playerName) sortName = p.preprocessSortName(sortName) if sortName ~= "" then -- if we have a sort name supplied return sortName -- then return it end -- players from certain countries will use name in order supplied local noSort = { "CAM", "CHN", "TPE", "MYA", "PRK", "KOR", "VIE" } for k,v in pairs(noSort) do if v == countryName then return playerName end end -- else work it out from the supplied player name -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (playerName, "|") then -- test for redirect local names = mw.text.split( playerName, "|") playerName = names[2] -- get name after pipe end local names = mw.text.split( playerName, " ") -- we don't want to sort on first name if #names == 1 then return names[1] -- return name of single name player else -- we will assume the second name is the sort name e.g, Joe Bloggs, Jan van Bloggen local name = names[2] -- set name to second name e.g. Bloggs or van local i=3 while i <= #names do -- any addition names e.g. Bloggen name= name .. names[i] i=i+1 end name = name .. ", " .. names[1] -- add first name e.g. Joe or Jan return name -- sort on second name third name etc, first name end end -- sort the list of countries alphabetically function p.sortComment(comment) local items = mw.text.split( comment, ",") -- split comma-delimited list for k,v in pairs(items) do items[k] = mw.text.trim(v) -- trim spaces and coe end table.sort(items, function(a,b) return a<b end) -- sort the table alphbetically local list = "against " -- construct the alphabetical list string for i=1, #items do local sep = ", " -- separator for comma-delimited list if i==1 then sep = "" -- first word doesn't need comma elseif i==#items then sep = " & " -- use "and" before last word end list = list .. sep .. items[i] end return list end function p.getCountryName(country) if string.len(country) == 3 then -- if the country given as a three-letter code local codes = require('Module:Goalscorers/data/Country codes') for k,v in pairs(codes.alias) do if v[1] == country then return v[2] end end else return country -- return the country name as is end end --[[ sort goalscorers by goals, country and name the sort first sorts by number of goals when these are equal, it sorts by country when these are equal, it sorts by name Note: the name sort is on the first name - a split of the name and sort on the last name is possible - however, this would be complicated by Dutch (e.g. Stefan de Vrij) and Spanish names - would sort on second name be better ]] function p.sortGoalscorers() local sort_function = function( a,b ) if (a.goals > b.goals) then -- primary sort on 'goals' -> a before b return true elseif (a.goals < b.goals) then -- primary sort on 'goals' -> b before a return false else -- a.goals == b.goals -- primary sort tied, --return a.country < b.country -- resolve with secondary sort on 'country' local country_a = p.getCountryName(a.country) -- sort on name of country, not the code local country_b = p.getCountryName(b.country) if (country_a < country_b) then -- secondary sort on 'country' return true elseif (country_a > country_b) then -- secondary sort on 'country' return false else -- a.country == b.country -- secondary sort tied, --return a.player < b.player --resolve with tertiary sort on 'player' name local player_a = p.getPlayerSortName(a.player, a.alias, a.country) -- get player name for sorting local player_b = p.getPlayerSortName(b.player, b.alias, b.country) return player_a < player_b -- --[[] --local test_a, test_b = a.player, b.player -- we don't want to test the name in a redirect, so get name after pipe if there is one if string.find (a.player, "|") then -- test for redirect local names = mw.text.split( a.player, "|") test_a = names[2] -- get name after pipe end if string.find (b.player, "|") then local names = mw.text.split( b.player, "|") test_b = names[2] end local names_a = mw.text.split( test_a, " ") -- we don't want to sort on first name local names_b = mw.text.split( test_b, " ") -- so split names if not names_a[2] then names_a[2] = test_a end -- for players with one name if not names_b[2] then names_b[2] = test_b end return names_a[2] < names_b[2] -- sort on second name ]] end end end table.sort(g.goalscorers, sort_function) end function p.tabulateGoalscorers(frame, og) -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 local maxRank = tonumber(g.args['maxrank'] or 10) -- limit list top ten or value in parameter maxrank local rank = 1 local playerCount = 0 local rankCount = 0 local playerCells = "" local firstplayerCell = "" local tableString = '\n{| class="wikitable"' -- start table ..'\n|-' .. '\n!Rank !! Player !! Goals' -- add table headers if g.args['header'] then tableString = tableString .. '\n|+ ' .. g.args['header'] end -- add header for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for tablulated list local goalscorerString = p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " '''" .. u['player'] .. "'''>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] -- comment for o.g. -- we have a goalscorer playerCount = playerCount + 1 rankCount = rankCount + 1 if u['goals'] < goalNumber then -- player belongs to rowspan for new number of goals -- need to generate code for the previous rowspan (if there is one) -- then start the counts and player list for the new one if playerCount == 1 then firstplayerCell = '\n|' .. goalscorerString -- if first player in list just create cell and set goals goalNumber = u['goals'] --rank = 1 rankCount = 0 else -- else generate previous rowspan local rowSpan = rankCount if playerCount > maxRank * 1.5 then firstplayerCell = '\n| style="font-style:italic;text-align:center;"|' .. rankCount .. " players" playerCells = "" rowSpan = 1 end tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank --if rankCount > 1 then tableString = tableString .. "=" end -- adds equals when rank shared tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells rank = rank + rankCount if rank > maxRank then break end -- limit list top ten or value in parameter rankCount = 0 goalNumber = u['goals'] firstplayerCell = '\n|' .. goalscorerString -- set first player cell for next rowspan playerCells = "" end else -- else another player with same number of goals playerCells = playerCells .. '\n|-' .. '\n|' .. goalscorerString -- add to player cell list end end -- reached end of list of goalscorers [for j,u loop] -- if all scorers on one goal, tableString isn't updated in loop above (may need to generalise for other goal number) if goalNumber == 1 and rank <= maxRank then local rowSpan = rankCount + 1 tableString = tableString .. '\n|-\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. rank tableString = tableString .. firstplayerCell tableString = tableString .. '\n| style="text-align:center;" rowspan="' .. rowSpan .. '"|' .. goalNumber tableString = tableString .. playerCells end if tableString ~= "" then tableString = tableString .. "\n|}" return tableString else return (" No goals matching requested criteria.") end end function p.outputGoalscorers(frame, og) -- output list of goalscorers if g.args['table'] then return p.tabulateGoalscorers(frame, og) end -- optional table output local outputString = "" if og == "OG" then end -- ==============output the lists of goalscorers by goal====================== local goalNumber = 1000 --local goalMinimum = tonumber(templateArgs['minimum']) or 0 local listOpen = false -- flag for list started by template {{Div Col}} for j,u in pairs(g.goalscorers) do -- run through sorted list of selected goalscorers --if u['goals'] < goalMinimum then break end -- limit list to goals over a threshold (now handled in select goalscorers) if u['goals'] < goalNumber then -- start new list of new number of goals if listOpen then -- if an open list, close last list outputString = outputString .. p.closeList(frame) listOpen = false -- redundant as will be set true again end goalNumber = u['goals'] local goalString = " goal" --if og == "OG" then if goalNumber < 0 then goalString = " own" .. goalString end if math.abs(u['goals']) ~= 1 then goalString = goalString .. "s" end outputString = outputString .. "\n'''" .. math.abs(u['goals']) .. goalString .. "'''" -- list caption outputString = outputString .. p.openList(frame,og) --start new list listOpen = true --goalNumber = u['goals'] end -- is the player active still? local playerActive = false if data.active_countries then for k,v in pairs(data.active_countries) do if v == u['country'] then playerActive = true break; end end end local _,roundStatus = p.getNumberMatches() if roundStatus == "complete" then playerActive = false end -- overrides active_countries -- wikitext for bullet list local goalscorerString = '\n*<span>' .. p.addLinkedIcon(frame, u['country']) -- linked flag icon if playerActive and g.args['bold']~='no' then goalscorerString = goalscorerString .. " <b>" .. u['player'] .. "</b>" -- bolded name else goalscorerString = goalscorerString .. " " .. u['player'] -- name end goalscorerString = goalscorerString .. u['comment'] .. '</span>' -- comment for o.g. outputString = outputString .. goalscorerString -- .. " " .. tostring(u['goals']) end -- reached end of list of goalscorers if outputString ~= "" then outputString = outputString .. p.closeList(frame) return outputString else return (" No goals matching requested criteria.") end end -- output icon linked to national team page function p.addLinkedIcon(frame, country) g.iconCache = g.iconCache or {} local cache = g.iconCache[data] -- per data module (safe across invokes) if not cache then cache = {}; g.iconCache[data] = cache end if cache[country] ~= nil then return cache[country] end -- already built for this team local icon = data.templates['flag_icon_linked'] -- fbicon etc set in data module local flagVariant = data.templates.flagvar and data.templates.flagvar[country] local result if icon == 'fbicon' then -- {{#invoke:flagg|main|pxxl|avar=fb|variant=VAR|CODE}} local args = { 'pxxl', country, avar = 'fb' } if flagVariant then args.variant = flagVariant end result = require('Module:Flagg').main(frame:newChild{ args = args }) else local level = data.templates['youth_level'] or "" -- youth level, e.g. under-21 if level ~= "" then result = frame:expandTemplate{ title = icon, args = { level, country, flagVariant or "" } } else result = frame:expandTemplate{ title = icon, args = { country, flagVariant or "" } } end end cache[country] = result return result end -- formatting of list under each number of goals function p.openList(frame,og) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '<div class="div-col" style="column-width:25em;">' -- perhaps add "column-count:3;"" to limit max number of columns? end function p.closeList(frame) return '</div>' end function p.firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- handles parameters bold, further, extra function p.addAdditionHeaderText(text, dateUpdated) if g.args['inlineref'] then text = text .. g.args['inlineref'] end if g.args['bold'] and g.args['bold']~='no' then text = text .. " Players highlighted in '''bold''' are still active in the competition." end if g.args['further'] then if text ~= "" then text = text .. " " end text = text .. g.args['further'] end if g.args['extra'] then text = text .. "\n\n" .. g.args['extra'] end return text end -- count number of goals for data in template function p.countGoals(list, number, totalGoals) local split = mw.text.split( list, "\n", true ) -- split the list for number of goals scorers with N goals local count = #split * math.abs(number) -- calculate number of goals (including own goals) totalGoals = totalGoals + count --mw.addWarning( "Entry: " .. list .. "[" .. count .. "]") return totalGoals end --[[ use data supplied by template ]] --function p.list(frame) function p.useTemplateData(frame) --getArgs(frame) --[[ {{{#if:{{{assists|}}}||There {{#if:{{{ongoing|}}}|{{#ifexpr:{{{goals}}}=1|has|have}} been |{{#ifexpr:{{{goals}}}=1|was|were}}}} {{{goals}}} {{#ifexpr:{{{goals}}}=1|goal|goals}} scored{{#if:{{{players|}}}|&nbsp;by {{{players}}} {{#ifexpr:{{{players}}}=1|player|different players}} {{#if:{{{own goals|}}}|&nbsp;(with {{{own goals}}} of them credited as {{#ifexpr:{{{own goals}}}=1|an own goal|own goals}})|}}|}} in {{{matches}}} {{#ifexpr:{{{matches}}}=1|match|matches}}, for an average of {{#expr:{{{goals}}}/{{{matches}}} round 2}} {{#ifexpr:({{{goals}}}/{{{matches}}} round 2)=1|goal|goals}} per match {{#if:{{{updated|}}}|&nbsp;(as of {{{updated}}})}}.}}{{#if:{{{bold|}}}|{{#if:{{{assists|}}}||&nbsp;}} Players highlighted in '''bold''' are still active in the competition. |}}{{#if:{{{further|}}}|{{#if:{{{assists|}}}||&nbsp;}}{{{further}}}|}} {{#if:{{{extra|}}}|{{{extra}}}{{clear}}|}} --]] local statNumber = mw.getLanguage('en'):formatNum( tonumber( g.args['goals'] or 0) ) --format goal number as string local matches = g.args['matches'] local statType = "goal" if g.args['assists'] then statType = "assist" end if g.args['clean sheets'] then statType = "clean sheet" end local ongoing = g.args['ongoing'] local text1 = "There" if g.args['lc'] then text1 = "there" end local text2 = "were" if ongoing then text2 = "have been" end local updateString = "" local averageString = "" local goalPlural = "s" -- goal(s) if g.args['goals'] and tonumber(g.args['goals']) == 1 then goalPlural = "" text2 = "was" if ongoing then text2 = "has been" end end local matchPlural = "es" -- match(es) if g.args['matches'] and tonumber(g.args['matches']) == 1 then matchPlural = "" end -- auto version: string.format(" in %d match%s, for an average of %."..precision.."g goal%s per match", matches, pluralMatches, average, pluralAverage) if g.args['goals'] and g.args['matches'] then local averageGoals = g.args['goals']/g.args['matches'] local avGoalPlural = "s" if averageGoals == 1 then avGoalPlural = "" end averageString = string.format(" in %d match%s, for an average of %.3g goal%s per match", g.args['matches'], matchPlural, averageGoals, avGoalPlural) end if g.args['updated'] and g.args['updated'] ~= "complete" then updateString = "&nbsp;(as of " ..g.args['updated'] .. ")" end local sep = "." if g.args['sep'] then sep = g.args['sep'] end local text = "" if g.args['goals'] then text = string.format("%s %s %s %s%s scored%s", text1, text2, statNumber, statType, goalPlural, averageString..updateString..sep) end text = p.addAdditionHeaderText(text) -- handles template parameters bold, further, extra --[[ {{#if:{{{30 goals|{{{30 assists|}}}}}}|'''30 {{#if:{{{assists|}}}|assists|goals}}''' <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{#if:{{{assists|}}}|{{{30 assists}}}|{{{30 goals}}}}}</div>|}}]] local output = "\n" local number = 30 local totalGoals = 0 while number > -4 do -- for the each goals/assists local entry = g.args[number .. ' goals'] or g.args[number .. ' goal'] or g.args[number .. ' assists'] or g.args[number .. ' assist'] or g.args[number .. ' clean sheets'] or g.args[number .. ' clean sheet'] if number < 0 then entry = g.args[math.abs(number) .. ' own goals'] or g.args[math.abs(number) .. ' own goal'] statType = "own goal" end local plural = "s" if number == 1 or number == -1 then plural = "" end if entry then -- do we have goals/assists for this number output = output .. "\n'''" .. tostring(math.abs(number)) .. " " .. statType .. plural .. "'''\n" .. p.openList(frame) .. "\n" .. entry .. p.closeList(frame) totalGoals = p.countGoals(entry, number, totalGoals) end number = number -1 end if statType == "goal" or statType == "own goal" then if g.args['goals'] and totalGoals ~= tonumber(g.args['goals']) then mw.addWarning("WARNING. Mismatch between number of goals listed (" .. totalGoals .. ") and goals parameter (" .. g.args['goals'] .. ").") end end --{{#if:{{{bottom|}}}|{{small|{{{bottom_text}}}}} <div class="div-col columns column-count column-count-3" style="column-count:3;"> {{{bottom}}}</div>|}}{{#if:{{{source|}}}|{{smaller|Source: {{{source}}}}}|}} local footerText = g.args['footer-text'] or g.args['bottom'] or "" local footerHeading = g.args['footer-heading'] or g.args['bottom-text'] or "" local footer = "" if footerText ~= "" then local heading = "" if footerHeading ~= "" then heading = '<p>' .. footerHeading .. '</p>' end footer = '\n' .. heading .. p.openList(frame) .. '\n' .. footerText .. p.closeList(frame) end --{{#if:{{{source|}}}|{{small|Source: {{{source}}}}}|}} local source = g.args['source'] or "" if source ~= "" then source = "<small>Source: " .. source .. "</small>" end return text .. output .. footer .. source end --[[ ######################## top scorer output ############################### p.topscorer(frame) - output the top goalscorer(s) for the whole competition |maxlist= how many tied players to list before collapsing to generic "N players" text (default 5) |basepage= page used in the collapsed link (default: current page) |section= section anchor for that link (default: Goalscorers) ]] function p.topscorer(frame) getArgs(frame) local dataTarget = g.args[1] or g.args['data'] if not dataTarget then return "" end -- this feature needs module data data = require('Module:Goalscorers/data/' .. dataTarget) g.goalscorers = {} -- reset state (safe across invokes) g.totalGoals = 0 local ok = p.selectGoalscorers() -- regular goals only; own goals ignored if not ok then return p.error_msg() end p.sortGoalscorers() -- sorts by goals desc, then country, name if #g.goalscorers == 0 then return "" end -- no scorers -> output nothing -- collect the tied leaders (sorted, so they sit at the front of the list) local topGoals = g.goalscorers[1].goals local leaders = {} for _, v in ipairs(g.goalscorers) do if v.goals == topGoals then leaders[#leaders + 1] = v else break end end local numTied = #leaders local maxList = tonumber(g.args['maxlist']) or 5 local goalWord = (topGoals == 1) and "goal" or "goals" local output if numTied == 1 then -- single top scorer local v = leaders[1] output = p.addLinkedIcon(frame, v.country) .. " " .. v.player .. ' <span class="nowrap">(' .. topGoals .. ' ' .. goalWord .. ')</span>' elseif numTied <= maxList then -- list each tied player local mList = require('Module:List') local listArgs = { class = 'nowrap' } for _, v in ipairs(leaders) do listArgs[#listArgs + 1] = p.addLinkedIcon(frame, v.country) .. " " .. v.player end listArgs[#listArgs + 1] = '(' .. topGoals .. ' ' .. goalWord .. ' each)' output = mList.makeList('unbulleted', listArgs) else -- too many tied -> generic text local mList = require('Module:List') local cn = require('Module:ConvertNumeric') local writtenNum = cn.spell_number2{ num = numTied, capitalize = true } -- e.g. 7 -> "Seven" local basePage = g.args['basepage'] or mw.title.getCurrentTitle().text local section = g.args['section'] or 'Goalscorers' output = mList.makeList('unbulleted', { class = 'nowrap', "''[[" .. basePage .. "#" .. section .. "|" .. writtenNum .. " players]]''", '(' .. topGoals .. ' ' .. goalWord .. ' each)' }) end return p.error_msg() or output end return p r75cn9j2fxjrzn8x5ruc033d3cuei99 मोड्युल:Football attendance summation 828 150524 1361432 2026-05-20T02:02:30Z en>S.A. Julio 0 creating module 1361432 Scribunto text/plain local p = {} local function expandRange(str) if not str or str == '' then return nil end str = mw.text.trim(str) local s, e = str:match('^(.-)%-(.+)$') if not s then s, e = str, str end s, e = mw.text.trim(s), mw.text.trim(e) local sn, en = tonumber(s), tonumber(e) if sn and en then if sn > en then return nil end local r = {} for i = sn, en do r[#r + 1] = tostring(i) end return r end if #s == 1 and #e == 1 then local sb, eb = s:byte(), e:byte() if sb > eb then return nil end if (sb >= 65 and sb <= 90 and eb >= 65 and eb <= 90) or (sb >= 97 and sb <= 122 and eb >= 97 and eb <= 122) then local r = {} for b = sb, eb do r[#r + 1] = string.char(b) end return r end end return nil end local function getContent(title) local t = mw.title.new(title) return t and t:getContent() or nil end local function extractSection(wikitext, section) local pattern = '<section%s+begin%s*=%s*"?' .. mw.text.trim(section):gsub('(%W)', '%%%1') .. '"?%s*/?%s*>(.-)<section%s+end%s*=%s*"?' .. mw.text.trim(section):gsub('(%W)', '%%%1') .. '"?%s*/?%s*>' local result = '' for match in wikitext:gmatch(pattern) do result = result .. match end return result end local function resolveLst(wikitext) return wikitext:gsub('{{%s*#[Ll]st%s*:%s*(.-)%s*|%s*(.-)%s*}}', function(article, section) local content = getContent(mw.text.trim(article)) return content and extractSection(content, section) or '' end):gsub('{{%s*#[Ss]ection%s*:%s*(.-)%s*|%s*(.-)%s*}}', function(article, section) local content = getContent(mw.text.trim(article)) return content and extractSection(content, section) or '' end) end local function parseAttendance(val) val = val:gsub('<ref[^>]*>.-</ref>', ''):gsub('<ref[^>]*/>', ''):gsub('<ref[^>]*/?>', '') val = val:gsub(',', '') local num = mw.text.trim(val):match('^(%d+)') return num and tonumber(num) or 0 end local function sumAttendances(wikitext) if not wikitext then return 0 end wikitext = resolveLst(wikitext) local total = 0 local i, len = 1, #wikitext while i <= len - 1 do if wikitext:sub(i, i + 1) == '{{' then local after = wikitext:sub(i + 2) local isFB = after:match('^%s*[Ff]ootball%s+box%s*[|}]') or after:match('^%s*#invoke%s*:%s*[Ff]ootball%s+box%s*|') if isFB then local depth, j = 1, i + 2 while j <= len - 1 and depth > 0 do local two = wikitext:sub(j, j + 1) if two == '{{' then depth = depth + 1; j = j + 2 elseif two == '}}' then depth = depth - 1 if depth == 0 then local val = wikitext:sub(i + 2, j - 1):match('|%s*attendance%s*=%s*([^|}-]*)') if val then total = total + parseAttendance(val) end end j = j + 2 else j = j + 1 end end i = j else i = i + 1 end else i = i + 1 end end return total end function p.main(frame) local args = require('Module:Arguments').getArgs(frame) local base = mw.title.getCurrentTitle().text local total = 0 for _, param in ipairs({'groups', 'groups2'}) do local vals = expandRange(args[param]) if vals then for _, v in ipairs(vals) do total = total + sumAttendances(getContent(base .. ' Group ' .. v)) end end end total = total + sumAttendances(getContent(base .. ' knockout stage')) local n = 1 while args['extra' .. n] do total = total + sumAttendances(getContent(mw.text.trim(args['extra' .. n]))) n = n + 1 end return tostring(total) end return p ek0zjck0s1bvmb9p1m9ynkxpps9kk38 1361433 1361432 2026-05-20T02:46:07Z en>S.A. Julio 0 fixes 1361433 Scribunto text/plain local p = {} local function expandRange(str) if not str or str == '' then return nil end str = mw.text.trim(str) local s, e = str:match('^(.-)%-(.+)$') if not s then s, e = str, str end s, e = mw.text.trim(s), mw.text.trim(e) local sn, en = tonumber(s), tonumber(e) if sn and en then if sn > en then return nil end local r = {} for i = sn, en do r[#r + 1] = tostring(i) end return r end if #s == 1 and #e == 1 then local sb, eb = s:byte(), e:byte() if sb > eb then return nil end if (sb >= 65 and sb <= 90 and eb >= 65 and eb <= 90) or (sb >= 97 and sb <= 122 and eb >= 97 and eb <= 122) then local r = {} for b = sb, eb do r[#r + 1] = string.char(b) end return r end end return nil end local function resolveRedirect(content) if not content then return nil end local target = content:match('^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*%[%[%s*(.-)%s*[%]|]') return target end local function getContent(title, currentTitle, seen) local t = mw.title.new(title) if not t then return nil end local key = t.prefixedText if seen[key] then return nil end local content = t:getContent() if not content then return nil end local redir = resolveRedirect(content) if redir then local rt = mw.title.new(redir) if not rt then return nil end if rt.prefixedText == currentTitle then return nil end key = rt.prefixedText if seen[key] then return nil end content = rt:getContent() if not content then return nil end end seen[key] = true return content end local function extractSection(wikitext, section) local pattern = '<section%s+begin%s*=%s*"?' .. mw.text.trim(section):gsub('(%W)', '%%%1') .. '"?%s*/?%s*>(.-)<section%s+end%s*=%s*"?' .. mw.text.trim(section):gsub('(%W)', '%%%1') .. '"?%s*/?%s*>' local result = '' for match in wikitext:gmatch(pattern) do result = result .. match end return result end local function isLineupSection(section) local low = mw.text.trim(section):lower() return low == 'lineups' or low == 'line-ups' end local function resolveLst(wikitext, currentTitle, seen) return wikitext:gsub('{{%s*#[Ll]st%s*:%s*(.-)%s*|%s*(.-)%s*}}', function(article, section) if isLineupSection(section) then return '' end local content = getContent(mw.text.trim(article), currentTitle, seen) return content and extractSection(content, section) or '' end):gsub('{{%s*#[Ss]ection%s*:%s*(.-)%s*|%s*(.-)%s*}}', function(article, section) if isLineupSection(section) then return '' end local content = getContent(mw.text.trim(article), currentTitle, seen) return content and extractSection(content, section) or '' end) end local function parseAttendance(val) val = val:gsub('<ref[^>]*>.-</ref>', ''):gsub('<ref[^>]*/>', ''):gsub('<ref[^>]*/?>', '') val = val:gsub(',', '') local num = mw.text.trim(val):match('^(%d+)') return num and tonumber(num) or 0 end local function sumAttendances(wikitext, currentTitle, seen) if not wikitext then return 0 end wikitext = resolveLst(wikitext, currentTitle, seen) local total = 0 local i, len = 1, #wikitext while i <= len - 1 do if wikitext:sub(i, i + 1) == '{{' then local after = wikitext:sub(i + 2) local isFB = after:match('^%s*[Ff]ootball%s+box%s*[|}]') or after:match('^%s*#invoke%s*:%s*[Ff]ootball%s+box%s*|') if isFB then local depth, j = 1, i + 2 while j <= len - 1 and depth > 0 do local two = wikitext:sub(j, j + 1) if two == '{{' then depth = depth + 1; j = j + 2 elseif two == '}}' then depth = depth - 1 if depth == 0 then local val = wikitext:sub(i + 2, j - 1):match('|%s*attendance%s*=%s*([^|}-]*)') if val then total = total + parseAttendance(val) end end j = j + 2 else j = j + 1 end end i = j else i = i + 1 end else i = i + 1 end end return total end function p.main(frame) local args = require('Module:Arguments').getArgs(frame) local currentTitle = mw.title.getCurrentTitle().prefixedText local base = mw.title.getCurrentTitle().text local seen = {} local total = 0 for _, param in ipairs({'groups', 'groups2'}) do local vals = expandRange(args[param]) if vals then for _, v in ipairs(vals) do total = total + sumAttendances(getContent(base .. ' Group ' .. v, currentTitle, seen), currentTitle, seen) end end end total = total + sumAttendances(getContent(base .. ' knockout stage', currentTitle, seen), currentTitle, seen) local n = 1 while args['extra' .. n] do total = total + sumAttendances(getContent(mw.text.trim(args['extra' .. n]), currentTitle, seen), currentTitle, seen) n = n + 1 end return tostring(total) end return p 4bgag680fu5v7nqjzkw66u7k8n6f0vd 1361434 1361433 2026-05-29T17:46:32Z en>S.A. Julio 0 add features 1361434 Scribunto text/plain local p = {} local function expandRange(str) if not str or str == '' then return nil end str = mw.text.trim(str) local s, e = str:match('^(.-)%-(.+)$') if not s then s, e = str, str end s, e = mw.text.trim(s), mw.text.trim(e) local sn, en = tonumber(s), tonumber(e) if sn and en then if sn > en then return nil end local r = {} for i = sn, en do r[#r + 1] = tostring(i) end return r end if #s == 1 and #e == 1 then local sb, eb = s:byte(), e:byte() if sb > eb then return nil end if (sb >= 65 and sb <= 90 and eb >= 65 and eb <= 90) or (sb >= 97 and sb <= 122 and eb >= 97 and eb <= 122) then local r = {} for b = sb, eb do r[#r + 1] = string.char(b) end return r end end return nil end local groupAliases = { y='group stage', yes='group stage', league='league phase', lp='league phase', leaguephase='league phase', ls='league stage', leaguestage='league stage', } local function resolveRedirect(content) if not content then return nil end local target = content:match('^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*%[%[%s*(.-)%s*[%]|]') return target end local function getContent(title, currentTitle, seen) local t = mw.title.new(title) if not t then return nil end local key = t.prefixedText if seen[key] then return nil end local content = t:getContent() if not content then return nil end local redir = resolveRedirect(content) if redir then local rt = mw.title.new(redir) if not rt then return nil end if rt.prefixedText == currentTitle then return nil end key = rt.prefixedText if seen[key] then return nil end content = rt:getContent() if not content then return nil end end seen[key] = true return content end local function getContentFallback(title1, title2, currentTitle, seen) local c = getContent(title1, currentTitle, seen) if c then return c end return getContent(title2, currentTitle, seen) end local function extractSection(wikitext, section) local pattern = '<section%s+begin%s*=%s*"?' .. mw.text.trim(section):gsub('(%W)', '%%%1') .. '"?%s*/?%s*>(.-)<section%s+end%s*=%s*"?' .. mw.text.trim(section):gsub('(%W)', '%%%1') .. '"?%s*/?%s*>' local result = '' for match in wikitext:gmatch(pattern) do result = result .. match end return result end local function isLineupSection(section) local low = mw.text.trim(section):lower() return low == 'lineups' or low == 'line-ups' end local function resolveLst(wikitext, currentTitle, seen) return wikitext:gsub('{{%s*#[Ll]st%s*:%s*(.-)%s*|%s*(.-)%s*}}', function(article, section) if isLineupSection(section) then return '' end local content = getContent(mw.text.trim(article), currentTitle, seen) return content and extractSection(content, section) or '' end):gsub('{{%s*#[Ss]ection%s*:%s*(.-)%s*|%s*(.-)%s*}}', function(article, section) if isLineupSection(section) then return '' end local content = getContent(mw.text.trim(article), currentTitle, seen) return content and extractSection(content, section) or '' end):gsub('{{%s*:%s*([^|}]+).-}}', function(title) local content = getContent(mw.text.trim(title), currentTitle, seen) return content or '' end) end local function parseAttendance(val) val = val:gsub('<ref[^>]*>.-</ref>', ''):gsub('<ref[^>]*/>', ''):gsub('<ref[^>]*/?>', '') val = val:gsub(',', '') local num = mw.text.trim(val):match('^(%d+)') return num and tonumber(num) or 0 end local function sumAttendances(wikitext, currentTitle, seen) if not wikitext then return 0 end wikitext = resolveLst(wikitext, currentTitle, seen) local total = 0 local i, len = 1, #wikitext while i <= len - 1 do if wikitext:sub(i, i + 1) == '{{' then local after = wikitext:sub(i + 2) local isFB = after:match('^%s*[Ff]ootball%s+box%s*[|}]') or after:match('^%s*#invoke%s*:%s*[Ff]ootball%s+box%s*|') if isFB then local depth, j = 1, i + 2 while j <= len - 1 and depth > 0 do local two = wikitext:sub(j, j + 1) if two == '{{' then depth = depth + 1; j = j + 2 elseif two == '}}' then depth = depth - 1 if depth == 0 then local val = wikitext:sub(i + 2, j - 1):match('|%s*attendance%s*=%s*([^|}-]*)') if val then total = total + parseAttendance(val) end end j = j + 2 else j = j + 1 end end i = j else i = i + 1 end else i = i + 1 end end return total end function p.main(frame) local args = require('Module:Arguments').getArgs(frame) local currentTitle = mw.title.getCurrentTitle().prefixedText local base = mw.title.getCurrentTitle().text local seen = {} local total = 0 for _, param in ipairs({'groups', 'groups2'}) do local raw = args[param] if raw then local alias = groupAliases[mw.text.trim(raw):lower()] if alias then total = total + sumAttendances(getContent(base .. ' ' .. alias, currentTitle, seen), currentTitle, seen) else local vals = expandRange(raw) if vals then for _, v in ipairs(vals) do total = total + sumAttendances(getContent(base .. ' Group ' .. v, currentTitle, seen), currentTitle, seen) end end end end end total = total + sumAttendances(getContentFallback(base .. ' knockout stage', base .. ' knockout phase', currentTitle, seen), currentTitle, seen) local n = 1 while args['extra' .. n] do total = total + sumAttendances(getContent(mw.text.trim(args['extra' .. n]), currentTitle, seen), currentTitle, seen) n = n + 1 end return tostring(total) end return p 79s9qgbgrgke4kksyz41b7p95axpnha 1361435 1361434 2026-06-12T08:16:10Z पर्वत सुवेदी 31224 [[:en:Module:Football_attendance_summation]] बाट ३ संशोधन(हरू): आयात गर्दै 1361434 Scribunto text/plain local p = {} local function expandRange(str) if not str or str == '' then return nil end str = mw.text.trim(str) local s, e = str:match('^(.-)%-(.+)$') if not s then s, e = str, str end s, e = mw.text.trim(s), mw.text.trim(e) local sn, en = tonumber(s), tonumber(e) if sn and en then if sn > en then return nil end local r = {} for i = sn, en do r[#r + 1] = tostring(i) end return r end if #s == 1 and #e == 1 then local sb, eb = s:byte(), e:byte() if sb > eb then return nil end if (sb >= 65 and sb <= 90 and eb >= 65 and eb <= 90) or (sb >= 97 and sb <= 122 and eb >= 97 and eb <= 122) then local r = {} for b = sb, eb do r[#r + 1] = string.char(b) end return r end end return nil end local groupAliases = { y='group stage', yes='group stage', league='league phase', lp='league phase', leaguephase='league phase', ls='league stage', leaguestage='league stage', } local function resolveRedirect(content) if not content then return nil end local target = content:match('^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*%[%[%s*(.-)%s*[%]|]') return target end local function getContent(title, currentTitle, seen) local t = mw.title.new(title) if not t then return nil end local key = t.prefixedText if seen[key] then return nil end local content = t:getContent() if not content then return nil end local redir = resolveRedirect(content) if redir then local rt = mw.title.new(redir) if not rt then return nil end if rt.prefixedText == currentTitle then return nil end key = rt.prefixedText if seen[key] then return nil end content = rt:getContent() if not content then return nil end end seen[key] = true return content end local function getContentFallback(title1, title2, currentTitle, seen) local c = getContent(title1, currentTitle, seen) if c then return c end return getContent(title2, currentTitle, seen) end local function extractSection(wikitext, section) local pattern = '<section%s+begin%s*=%s*"?' .. mw.text.trim(section):gsub('(%W)', '%%%1') .. '"?%s*/?%s*>(.-)<section%s+end%s*=%s*"?' .. mw.text.trim(section):gsub('(%W)', '%%%1') .. '"?%s*/?%s*>' local result = '' for match in wikitext:gmatch(pattern) do result = result .. match end return result end local function isLineupSection(section) local low = mw.text.trim(section):lower() return low == 'lineups' or low == 'line-ups' end local function resolveLst(wikitext, currentTitle, seen) return wikitext:gsub('{{%s*#[Ll]st%s*:%s*(.-)%s*|%s*(.-)%s*}}', function(article, section) if isLineupSection(section) then return '' end local content = getContent(mw.text.trim(article), currentTitle, seen) return content and extractSection(content, section) or '' end):gsub('{{%s*#[Ss]ection%s*:%s*(.-)%s*|%s*(.-)%s*}}', function(article, section) if isLineupSection(section) then return '' end local content = getContent(mw.text.trim(article), currentTitle, seen) return content and extractSection(content, section) or '' end):gsub('{{%s*:%s*([^|}]+).-}}', function(title) local content = getContent(mw.text.trim(title), currentTitle, seen) return content or '' end) end local function parseAttendance(val) val = val:gsub('<ref[^>]*>.-</ref>', ''):gsub('<ref[^>]*/>', ''):gsub('<ref[^>]*/?>', '') val = val:gsub(',', '') local num = mw.text.trim(val):match('^(%d+)') return num and tonumber(num) or 0 end local function sumAttendances(wikitext, currentTitle, seen) if not wikitext then return 0 end wikitext = resolveLst(wikitext, currentTitle, seen) local total = 0 local i, len = 1, #wikitext while i <= len - 1 do if wikitext:sub(i, i + 1) == '{{' then local after = wikitext:sub(i + 2) local isFB = after:match('^%s*[Ff]ootball%s+box%s*[|}]') or after:match('^%s*#invoke%s*:%s*[Ff]ootball%s+box%s*|') if isFB then local depth, j = 1, i + 2 while j <= len - 1 and depth > 0 do local two = wikitext:sub(j, j + 1) if two == '{{' then depth = depth + 1; j = j + 2 elseif two == '}}' then depth = depth - 1 if depth == 0 then local val = wikitext:sub(i + 2, j - 1):match('|%s*attendance%s*=%s*([^|}-]*)') if val then total = total + parseAttendance(val) end end j = j + 2 else j = j + 1 end end i = j else i = i + 1 end else i = i + 1 end end return total end function p.main(frame) local args = require('Module:Arguments').getArgs(frame) local currentTitle = mw.title.getCurrentTitle().prefixedText local base = mw.title.getCurrentTitle().text local seen = {} local total = 0 for _, param in ipairs({'groups', 'groups2'}) do local raw = args[param] if raw then local alias = groupAliases[mw.text.trim(raw):lower()] if alias then total = total + sumAttendances(getContent(base .. ' ' .. alias, currentTitle, seen), currentTitle, seen) else local vals = expandRange(raw) if vals then for _, v in ipairs(vals) do total = total + sumAttendances(getContent(base .. ' Group ' .. v, currentTitle, seen), currentTitle, seen) end end end end end total = total + sumAttendances(getContentFallback(base .. ' knockout stage', base .. ' knockout phase', currentTitle, seen), currentTitle, seen) local n = 1 while args['extra' .. n] do total = total + sumAttendances(getContent(mw.text.trim(args['extra' .. n]), currentTitle, seen), currentTitle, seen) n = n + 1 end return tostring(total) end return p 79s9qgbgrgke4kksyz41b7p95axpnha मोड्युल:Goalscorers/data/2026 FIFA World Cup 828 150525 1361436 2026-06-03T07:14:27Z en>S.A. Julio 0 creating data page 1361436 Scribunto text/plain local data = {} -- flag template data.templates = { flag_icon_linked = "fbicon" } -- date and matches played of latest update data.updated = { -- round, matches, update date matches finished/total matches of day finals = { 0, "2026-06-11", "1/2" }, } data.groups = { -- DO NOT CHANGE THIS SECTION } -- controls which teams are still active in tournament, and therefore have their players bolded -- ONLY ENABLE THIS AFTER AT LEAST ONE OF THE GROUPS HAS CONCLUDED -- data.active_countries = { "ALG", "ARG", "AUS", "AUT", "BEL", "BIH", "BRA", "CPV", "CAN", "COL", "COD", "CIV", "CRO", "CUW", "CZE", "ECU", "EGY", "ENG", "FRA", "GER", "GHA", "HAI", "IRN", "IRQ", "JPN", "JOR", "KOR", "MEX", "MAR", "NED", "NZL", "NOR", "PAN", "PAR", "POR", "QAT", "KSA", "SCO", "SEN", "RSA", "ESP", "SWE", "SUI", "TUN", "TUR", "URU", "USA", "UZB" } -- rounds of competition data.rounds = { finals = 3 } -- DO NOT CHANGE -- all competition goalscorers data.goalscorers = { -- player wikilink, country, goals -- Algeria (ALG) -- {"[[PLAYER]]", "ALG", 0 }, -- Argentina (ARG) -- {"[[PLAYER]]", "ARG", 0 }, -- Australia (AUS) -- {"[[PLAYER]]", "AUS", 0 }, -- Austria (AUT) -- {"[[PLAYER]]", "AUT", 0 }, -- Belgium (BEL) -- {"[[PLAYER]]", "BEL", 0 }, -- Bosnia and Herzegovina (BIH) -- {"[[PLAYER]]", "BIH", 0 }, -- Brazil (BRA) -- {"[[PLAYER]]", "BRA", 0 }, -- Canada (CAN) -- {"[[PLAYER]]", "CAN", 0 }, -- Cape Verde (CPV) -- {"[[PLAYER]]", "CPV", 0 }, -- Colombia (COL) -- {"[[PLAYER]]", "COL", 0 }, -- Croatia (CRO) -- {"[[PLAYER]]", "CRO", 0 }, -- Curaçao (CUW) -- {"[[PLAYER]]", "CUW", 0 }, -- Czech Republic (CZE) -- {"[[PLAYER]]", "CZE", 0 }, -- DR Congo (COD) -- {"[[PLAYER]]", "COD", 0 }, -- Ecuador (ECU) -- {"[[PLAYER]]", "ECU", 0 }, -- Egypt (EGY) -- {"[[PLAYER]]", "EGY", 0 }, -- England (ENG) -- {"[[PLAYER]]", "ENG", 0 }, -- France (FRA) -- {"[[PLAYER]]", "FRA", 0 }, -- Germany (GER) -- {"[[PLAYER]]", "GER", 0 }, -- Ghana (GHA) -- {"[[PLAYER]]", "GHA", 0 }, -- Haiti (HAI) -- {"[[PLAYER]]", "HAI", 0 }, -- Iran (IRN) -- {"[[PLAYER]]", "IRN", 0 }, -- Iraq (IRQ) -- {"[[PLAYER]]", "IRQ", 0 }, -- Ivory Coast (CIV) -- {"[[PLAYER]]", "CIV", 0 }, -- Japan (JPN) -- {"[[PLAYER]]", "JPN", 0 }, -- Jordan (JOR) -- {"[[PLAYER]]", "JOR", 0 }, -- Mexico (MEX) -- {"[[PLAYER]]", "MEX", 0 }, -- Morocco (MAR) -- {"[[PLAYER]]", "MAR", 0 }, -- Netherlands (NED) -- {"[[PLAYER]]", "NED", 0 }, -- New Zealand (NZL) -- {"[[PLAYER]]", "NZL", 0 }, -- Norway (NOR) -- {"[[PLAYER]]", "NOR", 0 }, -- Panama (PAN) -- {"[[PLAYER]]", "PAN", 0 }, -- Paraguay (PAR) -- {"[[PLAYER]]", "PAR", 0 }, -- Portugal (POR) -- {"[[PLAYER]]", "POR", 0 }, -- Qatar (QAT) -- {"[[PLAYER]]", "QAT", 0 }, -- Saudi Arabia (KSA) -- {"[[PLAYER]]", "KSA", 0 }, -- Scotland (SCO) -- {"[[PLAYER]]", "SCO", 0 }, -- Senegal (SEN) -- {"[[PLAYER]]", "SEN", 0 }, -- South Africa (RSA) -- {"[[PLAYER]]", "RSA", 0 }, -- South Korea (KOR) -- {"[[PLAYER]]", "KOR", 0 }, -- Spain (ESP) -- {"[[PLAYER]]", "ESP", 0 }, -- Sweden (SWE) -- {"[[PLAYER]]", "SWE", 0 }, -- Switzerland (SUI) -- {"[[PLAYER]]", "SUI", 0 }, -- Tunisia (TUN) -- {"[[PLAYER]]", "TUN", 0 }, -- Turkey (TUR) -- {"[[PLAYER]]", "TUR", 0 }, -- United States (USA) -- {"[[PLAYER]]", "USA", 0 }, -- Uruguay (URU) -- {"[[PLAYER]]", "URU", 0 }, -- Uzbekistan (UZB) -- {"[[PLAYER]]", "UZB", 0 }, } -- all competition own goal scorers data.owngoalscorers = { -- player wikilink, country, { own goals, "own goal opponents" } -- {"[[PLAYER]]", "CODE", { 1, "OPPONENT" } }, } return data qt2w3iq0xindojhwgybuyjenauki750 1361437 1361436 2026-06-11T06:46:16Z en>S.A. Julio 0 adjust 1361437 Scribunto text/plain local data = {} -- flag template data.templates = { flag_icon_linked = "fbicon" } -- date and matches played of latest update data.updated = { -- round, matches, update date, matches finished so far/total matches of day finals = { 0, "2026-06-11", "1/2" }, } data.groups = { -- DO NOT CHANGE THIS SECTION } -- controls which teams are still active in tournament, and therefore have their players bolded -- ONLY ENABLE THIS AFTER AT LEAST ONE OF THE GROUPS HAS CONCLUDED -- data.active_countries = { "ALG", "ARG", "AUS", "AUT", "BEL", "BIH", "BRA", "CPV", "CAN", "COL", "COD", "CIV", "CRO", "CUW", "CZE", "ECU", "EGY", "ENG", "FRA", "GER", "GHA", "HAI", "IRN", "IRQ", "JPN", "JOR", "KOR", "MEX", "MAR", "NED", "NZL", "NOR", "PAN", "PAR", "POR", "QAT", "KSA", "SCO", "SEN", "RSA", "ESP", "SWE", "SUI", "TUN", "TUR", "URU", "USA", "UZB" } -- rounds of competition data.rounds = { finals = 3 } -- DO NOT CHANGE -- all competition goalscorers data.goalscorers = { -- player wikilink, country, goals -- Algeria (ALG) -- {"[[PLAYER]]", "ALG", 0 }, -- Argentina (ARG) -- {"[[PLAYER]]", "ARG", 0 }, -- Australia (AUS) -- {"[[PLAYER]]", "AUS", 0 }, -- Austria (AUT) -- {"[[PLAYER]]", "AUT", 0 }, -- Belgium (BEL) -- {"[[PLAYER]]", "BEL", 0 }, -- Bosnia and Herzegovina (BIH) -- {"[[PLAYER]]", "BIH", 0 }, -- Brazil (BRA) -- {"[[PLAYER]]", "BRA", 0 }, -- Canada (CAN) -- {"[[PLAYER]]", "CAN", 0 }, -- Cape Verde (CPV) -- {"[[PLAYER]]", "CPV", 0 }, -- Colombia (COL) -- {"[[PLAYER]]", "COL", 0 }, -- Croatia (CRO) -- {"[[PLAYER]]", "CRO", 0 }, -- Curaçao (CUW) -- {"[[PLAYER]]", "CUW", 0 }, -- Czech Republic (CZE) -- {"[[PLAYER]]", "CZE", 0 }, -- DR Congo (COD) -- {"[[PLAYER]]", "COD", 0 }, -- Ecuador (ECU) -- {"[[PLAYER]]", "ECU", 0 }, -- Egypt (EGY) -- {"[[PLAYER]]", "EGY", 0 }, -- England (ENG) -- {"[[PLAYER]]", "ENG", 0 }, -- France (FRA) -- {"[[PLAYER]]", "FRA", 0 }, -- Germany (GER) -- {"[[PLAYER]]", "GER", 0 }, -- Ghana (GHA) -- {"[[PLAYER]]", "GHA", 0 }, -- Haiti (HAI) -- {"[[PLAYER]]", "HAI", 0 }, -- Iran (IRN) -- {"[[PLAYER]]", "IRN", 0 }, -- Iraq (IRQ) -- {"[[PLAYER]]", "IRQ", 0 }, -- Ivory Coast (CIV) -- {"[[PLAYER]]", "CIV", 0 }, -- Japan (JPN) -- {"[[PLAYER]]", "JPN", 0 }, -- Jordan (JOR) -- {"[[PLAYER]]", "JOR", 0 }, -- Mexico (MEX) -- {"[[PLAYER]]", "MEX", 0 }, -- Morocco (MAR) -- {"[[PLAYER]]", "MAR", 0 }, -- Netherlands (NED) -- {"[[PLAYER]]", "NED", 0 }, -- New Zealand (NZL) -- {"[[PLAYER]]", "NZL", 0 }, -- Norway (NOR) -- {"[[PLAYER]]", "NOR", 0 }, -- Panama (PAN) -- {"[[PLAYER]]", "PAN", 0 }, -- Paraguay (PAR) -- {"[[PLAYER]]", "PAR", 0 }, -- Portugal (POR) -- {"[[PLAYER]]", "POR", 0 }, -- Qatar (QAT) -- {"[[PLAYER]]", "QAT", 0 }, -- Saudi Arabia (KSA) -- {"[[PLAYER]]", "KSA", 0 }, -- Scotland (SCO) -- {"[[PLAYER]]", "SCO", 0 }, -- Senegal (SEN) -- {"[[PLAYER]]", "SEN", 0 }, -- South Africa (RSA) -- {"[[PLAYER]]", "RSA", 0 }, -- South Korea (KOR) -- {"[[PLAYER]]", "KOR", 0 }, -- Spain (ESP) -- {"[[PLAYER]]", "ESP", 0 }, -- Sweden (SWE) -- {"[[PLAYER]]", "SWE", 0 }, -- Switzerland (SUI) -- {"[[PLAYER]]", "SUI", 0 }, -- Tunisia (TUN) -- {"[[PLAYER]]", "TUN", 0 }, -- Turkey (TUR) -- {"[[PLAYER]]", "TUR", 0 }, -- United States (USA) -- {"[[PLAYER]]", "USA", 0 }, -- Uruguay (URU) -- {"[[PLAYER]]", "URU", 0 }, -- Uzbekistan (UZB) -- {"[[PLAYER]]", "UZB", 0 }, } -- all competition own goal scorers data.owngoalscorers = { -- player wikilink, country, { own goals, "own goal opponents" } -- {"[[PLAYER]]", "CODE", { 1, "OPPONENT" } }, } return data nr9pq9txn3l3s0penxks9do454x3ahb 1361438 1361437 2026-06-11T21:04:01Z en>S.A. Julio 0 up 1361438 Scribunto text/plain local data = {} -- flag template data.templates = { flag_icon_linked = "fbicon" } -- date and matches played of latest update data.updated = { -- round, matches, update date, matches finished so far/total matches of day finals = { 1, "2026-06-11", "1/2" }, } data.groups = { -- DO NOT CHANGE THIS SECTION } -- controls which teams are still active in tournament, and therefore have their players bolded -- ONLY ENABLE THIS AFTER AT LEAST ONE OF THE GROUPS HAS CONCLUDED -- data.active_countries = { "ALG", "ARG", "AUS", "AUT", "BEL", "BIH", "BRA", "CPV", "CAN", "COL", "COD", "CIV", "CRO", "CUW", "CZE", "ECU", "EGY", "ENG", "FRA", "GER", "GHA", "HAI", "IRN", "IRQ", "JPN", "JOR", "KOR", "MEX", "MAR", "NED", "NZL", "NOR", "PAN", "PAR", "POR", "QAT", "KSA", "SCO", "SEN", "RSA", "ESP", "SWE", "SUI", "TUN", "TUR", "URU", "USA", "UZB" } -- rounds of competition data.rounds = { finals = 3 } -- DO NOT CHANGE -- all competition goalscorers data.goalscorers = { -- player wikilink, country, goals -- Algeria (ALG) -- {"[[PLAYER]]", "ALG", 0 }, -- Argentina (ARG) -- {"[[PLAYER]]", "ARG", 0 }, -- Australia (AUS) -- {"[[PLAYER]]", "AUS", 0 }, -- Austria (AUT) -- {"[[PLAYER]]", "AUT", 0 }, -- Belgium (BEL) -- {"[[PLAYER]]", "BEL", 0 }, -- Bosnia and Herzegovina (BIH) -- {"[[PLAYER]]", "BIH", 0 }, -- Brazil (BRA) -- {"[[PLAYER]]", "BRA", 0 }, -- Canada (CAN) -- {"[[PLAYER]]", "CAN", 0 }, -- Cape Verde (CPV) -- {"[[PLAYER]]", "CPV", 0 }, -- Colombia (COL) -- {"[[PLAYER]]", "COL", 0 }, -- Croatia (CRO) -- {"[[PLAYER]]", "CRO", 0 }, -- Curaçao (CUW) -- {"[[PLAYER]]", "CUW", 0 }, -- Czech Republic (CZE) -- {"[[PLAYER]]", "CZE", 0 }, -- DR Congo (COD) -- {"[[PLAYER]]", "COD", 0 }, -- Ecuador (ECU) -- {"[[PLAYER]]", "ECU", 0 }, -- Egypt (EGY) -- {"[[PLAYER]]", "EGY", 0 }, -- England (ENG) -- {"[[PLAYER]]", "ENG", 0 }, -- France (FRA) -- {"[[PLAYER]]", "FRA", 0 }, -- Germany (GER) -- {"[[PLAYER]]", "GER", 0 }, -- Ghana (GHA) -- {"[[PLAYER]]", "GHA", 0 }, -- Haiti (HAI) -- {"[[PLAYER]]", "HAI", 0 }, -- Iran (IRN) -- {"[[PLAYER]]", "IRN", 0 }, -- Iraq (IRQ) -- {"[[PLAYER]]", "IRQ", 0 }, -- Ivory Coast (CIV) -- {"[[PLAYER]]", "CIV", 0 }, -- Japan (JPN) -- {"[[PLAYER]]", "JPN", 0 }, -- Jordan (JOR) -- {"[[PLAYER]]", "JOR", 0 }, -- Mexico (MEX) {"[[Julián Quiñones]]", "MEX", 0 }, {"[[Raúl Jiménez]]", "MEX", 0 }, -- Morocco (MAR) -- {"[[PLAYER]]", "MAR", 0 }, -- Netherlands (NED) -- {"[[PLAYER]]", "NED", 0 }, -- New Zealand (NZL) -- {"[[PLAYER]]", "NZL", 0 }, -- Norway (NOR) -- {"[[PLAYER]]", "NOR", 0 }, -- Panama (PAN) -- {"[[PLAYER]]", "PAN", 0 }, -- Paraguay (PAR) -- {"[[PLAYER]]", "PAR", 0 }, -- Portugal (POR) -- {"[[PLAYER]]", "POR", 0 }, -- Qatar (QAT) -- {"[[PLAYER]]", "QAT", 0 }, -- Saudi Arabia (KSA) -- {"[[PLAYER]]", "KSA", 0 }, -- Scotland (SCO) -- {"[[PLAYER]]", "SCO", 0 }, -- Senegal (SEN) -- {"[[PLAYER]]", "SEN", 0 }, -- South Africa (RSA) -- {"[[PLAYER]]", "RSA", 0 }, -- South Korea (KOR) -- {"[[PLAYER]]", "KOR", 0 }, -- Spain (ESP) -- {"[[PLAYER]]", "ESP", 0 }, -- Sweden (SWE) -- {"[[PLAYER]]", "SWE", 0 }, -- Switzerland (SUI) -- {"[[PLAYER]]", "SUI", 0 }, -- Tunisia (TUN) -- {"[[PLAYER]]", "TUN", 0 }, -- Turkey (TUR) -- {"[[PLAYER]]", "TUR", 0 }, -- United States (USA) -- {"[[PLAYER]]", "USA", 0 }, -- Uruguay (URU) -- {"[[PLAYER]]", "URU", 0 }, -- Uzbekistan (UZB) -- {"[[PLAYER]]", "UZB", 0 }, } -- all competition own goal scorers data.owngoalscorers = { -- player wikilink, country, { own goals, "own goal opponents" } -- {"[[PLAYER]]", "CODE", { 1, "OPPONENT" } }, } return data br1623xpudqkvb8xtx7i0b1vcd4l97s 1361439 1361438 2026-06-11T21:05:16Z en>S.A. Julio 0 fix 1361439 Scribunto text/plain local data = {} -- flag template data.templates = { flag_icon_linked = "fbicon" } -- date and matches played of latest update data.updated = { -- round, matches, update date, matches finished so far/total matches of day finals = { 1, "2026-06-11", "1/2" }, } data.groups = { -- DO NOT CHANGE THIS SECTION } -- controls which teams are still active in tournament, and therefore have their players bolded -- ONLY ENABLE THIS AFTER AT LEAST ONE OF THE GROUPS HAS CONCLUDED -- data.active_countries = { "ALG", "ARG", "AUS", "AUT", "BEL", "BIH", "BRA", "CPV", "CAN", "COL", "COD", "CIV", "CRO", "CUW", "CZE", "ECU", "EGY", "ENG", "FRA", "GER", "GHA", "HAI", "IRN", "IRQ", "JPN", "JOR", "KOR", "MEX", "MAR", "NED", "NZL", "NOR", "PAN", "PAR", "POR", "QAT", "KSA", "SCO", "SEN", "RSA", "ESP", "SWE", "SUI", "TUN", "TUR", "URU", "USA", "UZB" } -- rounds of competition data.rounds = { finals = 3 } -- DO NOT CHANGE -- all competition goalscorers data.goalscorers = { -- player wikilink, country, goals -- Algeria (ALG) -- {"[[PLAYER]]", "ALG", 0 }, -- Argentina (ARG) -- {"[[PLAYER]]", "ARG", 0 }, -- Australia (AUS) -- {"[[PLAYER]]", "AUS", 0 }, -- Austria (AUT) -- {"[[PLAYER]]", "AUT", 0 }, -- Belgium (BEL) -- {"[[PLAYER]]", "BEL", 0 }, -- Bosnia and Herzegovina (BIH) -- {"[[PLAYER]]", "BIH", 0 }, -- Brazil (BRA) -- {"[[PLAYER]]", "BRA", 0 }, -- Canada (CAN) -- {"[[PLAYER]]", "CAN", 0 }, -- Cape Verde (CPV) -- {"[[PLAYER]]", "CPV", 0 }, -- Colombia (COL) -- {"[[PLAYER]]", "COL", 0 }, -- Croatia (CRO) -- {"[[PLAYER]]", "CRO", 0 }, -- Curaçao (CUW) -- {"[[PLAYER]]", "CUW", 0 }, -- Czech Republic (CZE) -- {"[[PLAYER]]", "CZE", 0 }, -- DR Congo (COD) -- {"[[PLAYER]]", "COD", 0 }, -- Ecuador (ECU) -- {"[[PLAYER]]", "ECU", 0 }, -- Egypt (EGY) -- {"[[PLAYER]]", "EGY", 0 }, -- England (ENG) -- {"[[PLAYER]]", "ENG", 0 }, -- France (FRA) -- {"[[PLAYER]]", "FRA", 0 }, -- Germany (GER) -- {"[[PLAYER]]", "GER", 0 }, -- Ghana (GHA) -- {"[[PLAYER]]", "GHA", 0 }, -- Haiti (HAI) -- {"[[PLAYER]]", "HAI", 0 }, -- Iran (IRN) -- {"[[PLAYER]]", "IRN", 0 }, -- Iraq (IRQ) -- {"[[PLAYER]]", "IRQ", 0 }, -- Ivory Coast (CIV) -- {"[[PLAYER]]", "CIV", 0 }, -- Japan (JPN) -- {"[[PLAYER]]", "JPN", 0 }, -- Jordan (JOR) -- {"[[PLAYER]]", "JOR", 0 }, -- Mexico (MEX) {"[[Julián Quiñones]]", "MEX", 1 }, {"[[Raúl Jiménez]]", "MEX", 1 }, -- Morocco (MAR) -- {"[[PLAYER]]", "MAR", 0 }, -- Netherlands (NED) -- {"[[PLAYER]]", "NED", 0 }, -- New Zealand (NZL) -- {"[[PLAYER]]", "NZL", 0 }, -- Norway (NOR) -- {"[[PLAYER]]", "NOR", 0 }, -- Panama (PAN) -- {"[[PLAYER]]", "PAN", 0 }, -- Paraguay (PAR) -- {"[[PLAYER]]", "PAR", 0 }, -- Portugal (POR) -- {"[[PLAYER]]", "POR", 0 }, -- Qatar (QAT) -- {"[[PLAYER]]", "QAT", 0 }, -- Saudi Arabia (KSA) -- {"[[PLAYER]]", "KSA", 0 }, -- Scotland (SCO) -- {"[[PLAYER]]", "SCO", 0 }, -- Senegal (SEN) -- {"[[PLAYER]]", "SEN", 0 }, -- South Africa (RSA) -- {"[[PLAYER]]", "RSA", 0 }, -- South Korea (KOR) -- {"[[PLAYER]]", "KOR", 0 }, -- Spain (ESP) -- {"[[PLAYER]]", "ESP", 0 }, -- Sweden (SWE) -- {"[[PLAYER]]", "SWE", 0 }, -- Switzerland (SUI) -- {"[[PLAYER]]", "SUI", 0 }, -- Tunisia (TUN) -- {"[[PLAYER]]", "TUN", 0 }, -- Turkey (TUR) -- {"[[PLAYER]]", "TUR", 0 }, -- United States (USA) -- {"[[PLAYER]]", "USA", 0 }, -- Uruguay (URU) -- {"[[PLAYER]]", "URU", 0 }, -- Uzbekistan (UZB) -- {"[[PLAYER]]", "UZB", 0 }, } -- all competition own goal scorers data.owngoalscorers = { -- player wikilink, country, { own goals, "own goal opponents" } -- {"[[PLAYER]]", "CODE", { 1, "OPPONENT" } }, } return data ncaze7zh9cqzjjonnosia8nkm215b0a 1361440 1361439 2026-06-12T03:59:37Z en>S.A. Julio 0 up 1361440 Scribunto text/plain local data = {} -- flag template data.templates = { flag_icon_linked = "fbicon" } -- date and matches played of latest update data.updated = { -- round, matches, update date, matches finished so far/total matches of day finals = { 2, "2026-06-11", "2/2" }, } data.groups = { -- DO NOT CHANGE THIS SECTION } -- controls which teams are still active in tournament, and therefore have their players bolded -- ONLY ENABLE THIS AFTER AT LEAST ONE OF THE GROUPS HAS CONCLUDED -- data.active_countries = { "ALG", "ARG", "AUS", "AUT", "BEL", "BIH", "BRA", "CPV", "CAN", "COL", "COD", "CIV", "CRO", "CUW", "CZE", "ECU", "EGY", "ENG", "FRA", "GER", "GHA", "HAI", "IRN", "IRQ", "JPN", "JOR", "KOR", "MEX", "MAR", "NED", "NZL", "NOR", "PAN", "PAR", "POR", "QAT", "KSA", "SCO", "SEN", "RSA", "ESP", "SWE", "SUI", "TUN", "TUR", "URU", "USA", "UZB" } -- rounds of competition data.rounds = { finals = 3 } -- DO NOT CHANGE -- all competition goalscorers data.goalscorers = { -- player wikilink, country, goals -- Algeria (ALG) -- {"[[PLAYER]]", "ALG", 0 }, -- Argentina (ARG) -- {"[[PLAYER]]", "ARG", 0 }, -- Australia (AUS) -- {"[[PLAYER]]", "AUS", 0 }, -- Austria (AUT) -- {"[[PLAYER]]", "AUT", 0 }, -- Belgium (BEL) -- {"[[PLAYER]]", "BEL", 0 }, -- Bosnia and Herzegovina (BIH) -- {"[[PLAYER]]", "BIH", 0 }, -- Brazil (BRA) -- {"[[PLAYER]]", "BRA", 0 }, -- Canada (CAN) -- {"[[PLAYER]]", "CAN", 0 }, -- Cape Verde (CPV) -- {"[[PLAYER]]", "CPV", 0 }, -- Colombia (COL) -- {"[[PLAYER]]", "COL", 0 }, -- Croatia (CRO) -- {"[[PLAYER]]", "CRO", 0 }, -- Curaçao (CUW) -- {"[[PLAYER]]", "CUW", 0 }, -- Czech Republic (CZE) -- {"[[Ladislav Krejčí (footballer, born 1999)|Ladislav Krejčí]]", "CZE", 1 }, -- DR Congo (COD) -- {"[[PLAYER]]", "COD", 0 }, -- Ecuador (ECU) -- {"[[PLAYER]]", "ECU", 0 }, -- Egypt (EGY) -- {"[[PLAYER]]", "EGY", 0 }, -- England (ENG) -- {"[[PLAYER]]", "ENG", 0 }, -- France (FRA) -- {"[[PLAYER]]", "FRA", 0 }, -- Germany (GER) -- {"[[PLAYER]]", "GER", 0 }, -- Ghana (GHA) -- {"[[PLAYER]]", "GHA", 0 }, -- Haiti (HAI) -- {"[[PLAYER]]", "HAI", 0 }, -- Iran (IRN) -- {"[[PLAYER]]", "IRN", 0 }, -- Iraq (IRQ) -- {"[[PLAYER]]", "IRQ", 0 }, -- Ivory Coast (CIV) -- {"[[PLAYER]]", "CIV", 0 }, -- Japan (JPN) -- {"[[PLAYER]]", "JPN", 0 }, -- Jordan (JOR) -- {"[[PLAYER]]", "JOR", 0 }, -- Mexico (MEX) {"[[Julián Quiñones]]", "MEX", 1 }, {"[[Raúl Jiménez]]", "MEX", 1 }, -- Morocco (MAR) -- {"[[PLAYER]]", "MAR", 0 }, -- Netherlands (NED) -- {"[[PLAYER]]", "NED", 0 }, -- New Zealand (NZL) -- {"[[PLAYER]]", "NZL", 0 }, -- Norway (NOR) -- {"[[PLAYER]]", "NOR", 0 }, -- Panama (PAN) -- {"[[PLAYER]]", "PAN", 0 }, -- Paraguay (PAR) -- {"[[PLAYER]]", "PAR", 0 }, -- Portugal (POR) -- {"[[PLAYER]]", "POR", 0 }, -- Qatar (QAT) -- {"[[PLAYER]]", "QAT", 0 }, -- Saudi Arabia (KSA) -- {"[[PLAYER]]", "KSA", 0 }, -- Scotland (SCO) -- {"[[PLAYER]]", "SCO", 0 }, -- Senegal (SEN) -- {"[[PLAYER]]", "SEN", 0 }, -- South Africa (RSA) -- {"[[PLAYER]]", "RSA", 0 }, -- South Korea (KOR) {"[[Hwang In-beom]]", "KOR", 1 }, {"[[Oh Hyeon-gyu]]", "KOR", 1 }, -- Spain (ESP) -- {"[[PLAYER]]", "ESP", 0 }, -- Sweden (SWE) -- {"[[PLAYER]]", "SWE", 0 }, -- Switzerland (SUI) -- {"[[PLAYER]]", "SUI", 0 }, -- Tunisia (TUN) -- {"[[PLAYER]]", "TUN", 0 }, -- Turkey (TUR) -- {"[[PLAYER]]", "TUR", 0 }, -- United States (USA) -- {"[[PLAYER]]", "USA", 0 }, -- Uruguay (URU) -- {"[[PLAYER]]", "URU", 0 }, -- Uzbekistan (UZB) -- {"[[PLAYER]]", "UZB", 0 }, } -- all competition own goal scorers data.owngoalscorers = { -- player wikilink, country, { own goals, "own goal opponents" } -- {"[[PLAYER]]", "CODE", { 1, "OPPONENT" } }, } return data ewlst38gxsh7aeb5i1bzdxkr3xu8emj 1361441 1361440 2026-06-12T04:03:58Z en>S.A. Julio 0 fix 1361441 Scribunto text/plain local data = {} -- flag template data.templates = { flag_icon_linked = "fbicon" } -- date and matches played of latest update data.updated = { -- round, matches, update date, matches finished so far/total matches of day finals = { 2, "2026-06-11", "2/2" }, } data.groups = { -- DO NOT CHANGE THIS SECTION } -- controls which teams are still active in tournament, and therefore have their players bolded -- ONLY ENABLE THIS AFTER AT LEAST ONE OF THE GROUPS HAS CONCLUDED -- data.active_countries = { "ALG", "ARG", "AUS", "AUT", "BEL", "BIH", "BRA", "CPV", "CAN", "COL", "COD", "CIV", "CRO", "CUW", "CZE", "ECU", "EGY", "ENG", "FRA", "GER", "GHA", "HAI", "IRN", "IRQ", "JPN", "JOR", "KOR", "MEX", "MAR", "NED", "NZL", "NOR", "PAN", "PAR", "POR", "QAT", "KSA", "SCO", "SEN", "RSA", "ESP", "SWE", "SUI", "TUN", "TUR", "URU", "USA", "UZB" } -- rounds of competition data.rounds = { finals = 3 } -- DO NOT CHANGE -- all competition goalscorers data.goalscorers = { -- player wikilink, country, goals -- Algeria (ALG) -- {"[[PLAYER]]", "ALG", 0 }, -- Argentina (ARG) -- {"[[PLAYER]]", "ARG", 0 }, -- Australia (AUS) -- {"[[PLAYER]]", "AUS", 0 }, -- Austria (AUT) -- {"[[PLAYER]]", "AUT", 0 }, -- Belgium (BEL) -- {"[[PLAYER]]", "BEL", 0 }, -- Bosnia and Herzegovina (BIH) -- {"[[PLAYER]]", "BIH", 0 }, -- Brazil (BRA) -- {"[[PLAYER]]", "BRA", 0 }, -- Canada (CAN) -- {"[[PLAYER]]", "CAN", 0 }, -- Cape Verde (CPV) -- {"[[PLAYER]]", "CPV", 0 }, -- Colombia (COL) -- {"[[PLAYER]]", "COL", 0 }, -- Croatia (CRO) -- {"[[PLAYER]]", "CRO", 0 }, -- Curaçao (CUW) -- {"[[PLAYER]]", "CUW", 0 }, -- Czech Republic (CZE) {"[[Ladislav Krejčí (footballer, born 1999)|Ladislav Krejčí]]", "CZE", 1 }, -- DR Congo (COD) -- {"[[PLAYER]]", "COD", 0 }, -- Ecuador (ECU) -- {"[[PLAYER]]", "ECU", 0 }, -- Egypt (EGY) -- {"[[PLAYER]]", "EGY", 0 }, -- England (ENG) -- {"[[PLAYER]]", "ENG", 0 }, -- France (FRA) -- {"[[PLAYER]]", "FRA", 0 }, -- Germany (GER) -- {"[[PLAYER]]", "GER", 0 }, -- Ghana (GHA) -- {"[[PLAYER]]", "GHA", 0 }, -- Haiti (HAI) -- {"[[PLAYER]]", "HAI", 0 }, -- Iran (IRN) -- {"[[PLAYER]]", "IRN", 0 }, -- Iraq (IRQ) -- {"[[PLAYER]]", "IRQ", 0 }, -- Ivory Coast (CIV) -- {"[[PLAYER]]", "CIV", 0 }, -- Japan (JPN) -- {"[[PLAYER]]", "JPN", 0 }, -- Jordan (JOR) -- {"[[PLAYER]]", "JOR", 0 }, -- Mexico (MEX) {"[[Julián Quiñones]]", "MEX", 1 }, {"[[Raúl Jiménez]]", "MEX", 1 }, -- Morocco (MAR) -- {"[[PLAYER]]", "MAR", 0 }, -- Netherlands (NED) -- {"[[PLAYER]]", "NED", 0 }, -- New Zealand (NZL) -- {"[[PLAYER]]", "NZL", 0 }, -- Norway (NOR) -- {"[[PLAYER]]", "NOR", 0 }, -- Panama (PAN) -- {"[[PLAYER]]", "PAN", 0 }, -- Paraguay (PAR) -- {"[[PLAYER]]", "PAR", 0 }, -- Portugal (POR) -- {"[[PLAYER]]", "POR", 0 }, -- Qatar (QAT) -- {"[[PLAYER]]", "QAT", 0 }, -- Saudi Arabia (KSA) -- {"[[PLAYER]]", "KSA", 0 }, -- Scotland (SCO) -- {"[[PLAYER]]", "SCO", 0 }, -- Senegal (SEN) -- {"[[PLAYER]]", "SEN", 0 }, -- South Africa (RSA) -- {"[[PLAYER]]", "RSA", 0 }, -- South Korea (KOR) {"[[Hwang In-beom]]", "KOR", 1 }, {"[[Oh Hyeon-gyu]]", "KOR", 1 }, -- Spain (ESP) -- {"[[PLAYER]]", "ESP", 0 }, -- Sweden (SWE) -- {"[[PLAYER]]", "SWE", 0 }, -- Switzerland (SUI) -- {"[[PLAYER]]", "SUI", 0 }, -- Tunisia (TUN) -- {"[[PLAYER]]", "TUN", 0 }, -- Turkey (TUR) -- {"[[PLAYER]]", "TUR", 0 }, -- United States (USA) -- {"[[PLAYER]]", "USA", 0 }, -- Uruguay (URU) -- {"[[PLAYER]]", "URU", 0 }, -- Uzbekistan (UZB) -- {"[[PLAYER]]", "UZB", 0 }, } -- all competition own goal scorers data.owngoalscorers = { -- player wikilink, country, { own goals, "own goal opponents" } -- {"[[PLAYER]]", "CODE", { 1, "OPPONENT" } }, } return data km19isdel28tsxclmpnz6p7jako5lk5 1361442 1361441 2026-06-12T08:18:02Z पर्वत सुवेदी 31224 [[:en:Module:Goalscorers/data/2026_FIFA_World_Cup]] बाट ६ संशोधन(हरू) 1361441 Scribunto text/plain local data = {} -- flag template data.templates = { flag_icon_linked = "fbicon" } -- date and matches played of latest update data.updated = { -- round, matches, update date, matches finished so far/total matches of day finals = { 2, "2026-06-11", "2/2" }, } data.groups = { -- DO NOT CHANGE THIS SECTION } -- controls which teams are still active in tournament, and therefore have their players bolded -- ONLY ENABLE THIS AFTER AT LEAST ONE OF THE GROUPS HAS CONCLUDED -- data.active_countries = { "ALG", "ARG", "AUS", "AUT", "BEL", "BIH", "BRA", "CPV", "CAN", "COL", "COD", "CIV", "CRO", "CUW", "CZE", "ECU", "EGY", "ENG", "FRA", "GER", "GHA", "HAI", "IRN", "IRQ", "JPN", "JOR", "KOR", "MEX", "MAR", "NED", "NZL", "NOR", "PAN", "PAR", "POR", "QAT", "KSA", "SCO", "SEN", "RSA", "ESP", "SWE", "SUI", "TUN", "TUR", "URU", "USA", "UZB" } -- rounds of competition data.rounds = { finals = 3 } -- DO NOT CHANGE -- all competition goalscorers data.goalscorers = { -- player wikilink, country, goals -- Algeria (ALG) -- {"[[PLAYER]]", "ALG", 0 }, -- Argentina (ARG) -- {"[[PLAYER]]", "ARG", 0 }, -- Australia (AUS) -- {"[[PLAYER]]", "AUS", 0 }, -- Austria (AUT) -- {"[[PLAYER]]", "AUT", 0 }, -- Belgium (BEL) -- {"[[PLAYER]]", "BEL", 0 }, -- Bosnia and Herzegovina (BIH) -- {"[[PLAYER]]", "BIH", 0 }, -- Brazil (BRA) -- {"[[PLAYER]]", "BRA", 0 }, -- Canada (CAN) -- {"[[PLAYER]]", "CAN", 0 }, -- Cape Verde (CPV) -- {"[[PLAYER]]", "CPV", 0 }, -- Colombia (COL) -- {"[[PLAYER]]", "COL", 0 }, -- Croatia (CRO) -- {"[[PLAYER]]", "CRO", 0 }, -- Curaçao (CUW) -- {"[[PLAYER]]", "CUW", 0 }, -- Czech Republic (CZE) {"[[Ladislav Krejčí (footballer, born 1999)|Ladislav Krejčí]]", "CZE", 1 }, -- DR Congo (COD) -- {"[[PLAYER]]", "COD", 0 }, -- Ecuador (ECU) -- {"[[PLAYER]]", "ECU", 0 }, -- Egypt (EGY) -- {"[[PLAYER]]", "EGY", 0 }, -- England (ENG) -- {"[[PLAYER]]", "ENG", 0 }, -- France (FRA) -- {"[[PLAYER]]", "FRA", 0 }, -- Germany (GER) -- {"[[PLAYER]]", "GER", 0 }, -- Ghana (GHA) -- {"[[PLAYER]]", "GHA", 0 }, -- Haiti (HAI) -- {"[[PLAYER]]", "HAI", 0 }, -- Iran (IRN) -- {"[[PLAYER]]", "IRN", 0 }, -- Iraq (IRQ) -- {"[[PLAYER]]", "IRQ", 0 }, -- Ivory Coast (CIV) -- {"[[PLAYER]]", "CIV", 0 }, -- Japan (JPN) -- {"[[PLAYER]]", "JPN", 0 }, -- Jordan (JOR) -- {"[[PLAYER]]", "JOR", 0 }, -- Mexico (MEX) {"[[Julián Quiñones]]", "MEX", 1 }, {"[[Raúl Jiménez]]", "MEX", 1 }, -- Morocco (MAR) -- {"[[PLAYER]]", "MAR", 0 }, -- Netherlands (NED) -- {"[[PLAYER]]", "NED", 0 }, -- New Zealand (NZL) -- {"[[PLAYER]]", "NZL", 0 }, -- Norway (NOR) -- {"[[PLAYER]]", "NOR", 0 }, -- Panama (PAN) -- {"[[PLAYER]]", "PAN", 0 }, -- Paraguay (PAR) -- {"[[PLAYER]]", "PAR", 0 }, -- Portugal (POR) -- {"[[PLAYER]]", "POR", 0 }, -- Qatar (QAT) -- {"[[PLAYER]]", "QAT", 0 }, -- Saudi Arabia (KSA) -- {"[[PLAYER]]", "KSA", 0 }, -- Scotland (SCO) -- {"[[PLAYER]]", "SCO", 0 }, -- Senegal (SEN) -- {"[[PLAYER]]", "SEN", 0 }, -- South Africa (RSA) -- {"[[PLAYER]]", "RSA", 0 }, -- South Korea (KOR) {"[[Hwang In-beom]]", "KOR", 1 }, {"[[Oh Hyeon-gyu]]", "KOR", 1 }, -- Spain (ESP) -- {"[[PLAYER]]", "ESP", 0 }, -- Sweden (SWE) -- {"[[PLAYER]]", "SWE", 0 }, -- Switzerland (SUI) -- {"[[PLAYER]]", "SUI", 0 }, -- Tunisia (TUN) -- {"[[PLAYER]]", "TUN", 0 }, -- Turkey (TUR) -- {"[[PLAYER]]", "TUR", 0 }, -- United States (USA) -- {"[[PLAYER]]", "USA", 0 }, -- Uruguay (URU) -- {"[[PLAYER]]", "URU", 0 }, -- Uzbekistan (UZB) -- {"[[PLAYER]]", "UZB", 0 }, } -- all competition own goal scorers data.owngoalscorers = { -- player wikilink, country, { own goals, "own goal opponents" } -- {"[[PLAYER]]", "CODE", { 1, "OPPONENT" } }, } return data km19isdel28tsxclmpnz6p7jako5lk5 1361461 1361442 2026-06-12T08:40:57Z पर्वत सुवेदी 31224 परिक्षण 1361461 Scribunto text/plain local data = {} -- flag template data.templates = { flag_icon_linked = "fbicon" } -- date and matches played of latest update data.updated = { -- round, matches, update date, matches finished so far/total matches of day finals = { 2, "२०२६-०६-११", "२/२" }, } data.groups = { -- DO NOT CHANGE THIS SECTION } -- controls which teams are still active in tournament, and therefore have their players bolded -- ONLY ENABLE THIS AFTER AT LEAST ONE OF THE GROUPS HAS CONCLUDED -- data.active_countries = { "ALG", "ARG", "AUS", "AUT", "BEL", "BIH", "BRA", "CPV", "CAN", "COL", "COD", "CIV", "CRO", "CUW", "CZE", "ECU", "EGY", "ENG", "FRA", "GER", "GHA", "HAI", "IRN", "IRQ", "JPN", "JOR", "KOR", "MEX", "MAR", "NED", "NZL", "NOR", "PAN", "PAR", "POR", "QAT", "KSA", "SCO", "SEN", "RSA", "ESP", "SWE", "SUI", "TUN", "TUR", "URU", "USA", "UZB" } -- rounds of competition data.rounds = { finals = 3 } -- DO NOT CHANGE -- all competition goalscorers data.goalscorers = { -- player wikilink, country, goals -- Algeria (ALG) -- {"[[PLAYER]]", "ALG", 0 }, -- Argentina (ARG) -- {"[[PLAYER]]", "ARG", 0 }, -- Australia (AUS) -- {"[[PLAYER]]", "AUS", 0 }, -- Austria (AUT) -- {"[[PLAYER]]", "AUT", 0 }, -- Belgium (BEL) -- {"[[PLAYER]]", "BEL", 0 }, -- Bosnia and Herzegovina (BIH) -- {"[[PLAYER]]", "BIH", 0 }, -- Brazil (BRA) -- {"[[PLAYER]]", "BRA", 0 }, -- Canada (CAN) -- {"[[PLAYER]]", "CAN", 0 }, -- Cape Verde (CPV) -- {"[[PLAYER]]", "CPV", 0 }, -- Colombia (COL) -- {"[[PLAYER]]", "COL", 0 }, -- Croatia (CRO) -- {"[[PLAYER]]", "CRO", 0 }, -- Curaçao (CUW) -- {"[[PLAYER]]", "CUW", 0 }, -- Czech Republic (CZE) {"[[Ladislav Krejčí (footballer, born 1999)|Ladislav Krejčí]]", "CZE", 1 }, -- DR Congo (COD) -- {"[[PLAYER]]", "COD", 0 }, -- Ecuador (ECU) -- {"[[PLAYER]]", "ECU", 0 }, -- Egypt (EGY) -- {"[[PLAYER]]", "EGY", 0 }, -- England (ENG) -- {"[[PLAYER]]", "ENG", 0 }, -- France (FRA) -- {"[[PLAYER]]", "FRA", 0 }, -- Germany (GER) -- {"[[PLAYER]]", "GER", 0 }, -- Ghana (GHA) -- {"[[PLAYER]]", "GHA", 0 }, -- Haiti (HAI) -- {"[[PLAYER]]", "HAI", 0 }, -- Iran (IRN) -- {"[[PLAYER]]", "IRN", 0 }, -- Iraq (IRQ) -- {"[[PLAYER]]", "IRQ", 0 }, -- Ivory Coast (CIV) -- {"[[PLAYER]]", "CIV", 0 }, -- Japan (JPN) -- {"[[PLAYER]]", "JPN", 0 }, -- Jordan (JOR) -- {"[[PLAYER]]", "JOR", 0 }, -- Mexico (MEX) {"[[Julián Quiñones]]", "MEX", 1 }, {"[[Raúl Jiménez]]", "MEX", 1 }, -- Morocco (MAR) -- {"[[PLAYER]]", "MAR", 0 }, -- Netherlands (NED) -- {"[[PLAYER]]", "NED", 0 }, -- New Zealand (NZL) -- {"[[PLAYER]]", "NZL", 0 }, -- Norway (NOR) -- {"[[PLAYER]]", "NOR", 0 }, -- Panama (PAN) -- {"[[PLAYER]]", "PAN", 0 }, -- Paraguay (PAR) -- {"[[PLAYER]]", "PAR", 0 }, -- Portugal (POR) -- {"[[PLAYER]]", "POR", 0 }, -- Qatar (QAT) -- {"[[PLAYER]]", "QAT", 0 }, -- Saudi Arabia (KSA) -- {"[[PLAYER]]", "KSA", 0 }, -- Scotland (SCO) -- {"[[PLAYER]]", "SCO", 0 }, -- Senegal (SEN) -- {"[[PLAYER]]", "SEN", 0 }, -- South Africa (RSA) -- {"[[PLAYER]]", "RSA", 0 }, -- South Korea (KOR) {"[[Hwang In-beom]]", "KOR", 1 }, {"[[Oh Hyeon-gyu]]", "KOR", 1 }, -- Spain (ESP) -- {"[[PLAYER]]", "ESP", 0 }, -- Sweden (SWE) -- {"[[PLAYER]]", "SWE", 0 }, -- Switzerland (SUI) -- {"[[PLAYER]]", "SUI", 0 }, -- Tunisia (TUN) -- {"[[PLAYER]]", "TUN", 0 }, -- Turkey (TUR) -- {"[[PLAYER]]", "TUR", 0 }, -- United States (USA) -- {"[[PLAYER]]", "USA", 0 }, -- Uruguay (URU) -- {"[[PLAYER]]", "URU", 0 }, -- Uzbekistan (UZB) -- {"[[PLAYER]]", "UZB", 0 }, } -- all competition own goal scorers data.owngoalscorers = { -- player wikilink, country, { own goals, "own goal opponents" } -- {"[[PLAYER]]", "CODE", { 1, "OPPONENT" } }, } return data q59qzt67sdupb3d3umhhyecysqyve8i 1361462 1361461 2026-06-12T08:41:34Z पर्वत सुवेदी 31224 1361462 Scribunto text/plain local data = {} -- flag template data.templates = { flag_icon_linked = "fbicon" } -- date and matches played of latest update data.updated = { -- round, matches, update date, matches finished so far/total matches of day finals = { 2, "2026-06-11", "2/2" }, } data.groups = { -- DO NOT CHANGE THIS SECTION } -- controls which teams are still active in tournament, and therefore have their players bolded -- ONLY ENABLE THIS AFTER AT LEAST ONE OF THE GROUPS HAS CONCLUDED -- data.active_countries = { "ALG", "ARG", "AUS", "AUT", "BEL", "BIH", "BRA", "CPV", "CAN", "COL", "COD", "CIV", "CRO", "CUW", "CZE", "ECU", "EGY", "ENG", "FRA", "GER", "GHA", "HAI", "IRN", "IRQ", "JPN", "JOR", "KOR", "MEX", "MAR", "NED", "NZL", "NOR", "PAN", "PAR", "POR", "QAT", "KSA", "SCO", "SEN", "RSA", "ESP", "SWE", "SUI", "TUN", "TUR", "URU", "USA", "UZB" } -- rounds of competition data.rounds = { finals = 3 } -- DO NOT CHANGE -- all competition goalscorers data.goalscorers = { -- player wikilink, country, goals -- Algeria (ALG) -- {"[[PLAYER]]", "ALG", 0 }, -- Argentina (ARG) -- {"[[PLAYER]]", "ARG", 0 }, -- Australia (AUS) -- {"[[PLAYER]]", "AUS", 0 }, -- Austria (AUT) -- {"[[PLAYER]]", "AUT", 0 }, -- Belgium (BEL) -- {"[[PLAYER]]", "BEL", 0 }, -- Bosnia and Herzegovina (BIH) -- {"[[PLAYER]]", "BIH", 0 }, -- Brazil (BRA) -- {"[[PLAYER]]", "BRA", 0 }, -- Canada (CAN) -- {"[[PLAYER]]", "CAN", 0 }, -- Cape Verde (CPV) -- {"[[PLAYER]]", "CPV", 0 }, -- Colombia (COL) -- {"[[PLAYER]]", "COL", 0 }, -- Croatia (CRO) -- {"[[PLAYER]]", "CRO", 0 }, -- Curaçao (CUW) -- {"[[PLAYER]]", "CUW", 0 }, -- Czech Republic (CZE) {"[[Ladislav Krejčí (footballer, born 1999)|Ladislav Krejčí]]", "CZE", 1 }, -- DR Congo (COD) -- {"[[PLAYER]]", "COD", 0 }, -- Ecuador (ECU) -- {"[[PLAYER]]", "ECU", 0 }, -- Egypt (EGY) -- {"[[PLAYER]]", "EGY", 0 }, -- England (ENG) -- {"[[PLAYER]]", "ENG", 0 }, -- France (FRA) -- {"[[PLAYER]]", "FRA", 0 }, -- Germany (GER) -- {"[[PLAYER]]", "GER", 0 }, -- Ghana (GHA) -- {"[[PLAYER]]", "GHA", 0 }, -- Haiti (HAI) -- {"[[PLAYER]]", "HAI", 0 }, -- Iran (IRN) -- {"[[PLAYER]]", "IRN", 0 }, -- Iraq (IRQ) -- {"[[PLAYER]]", "IRQ", 0 }, -- Ivory Coast (CIV) -- {"[[PLAYER]]", "CIV", 0 }, -- Japan (JPN) -- {"[[PLAYER]]", "JPN", 0 }, -- Jordan (JOR) -- {"[[PLAYER]]", "JOR", 0 }, -- Mexico (MEX) {"[[Julián Quiñones]]", "MEX", 1 }, {"[[Raúl Jiménez]]", "MEX", 1 }, -- Morocco (MAR) -- {"[[PLAYER]]", "MAR", 0 }, -- Netherlands (NED) -- {"[[PLAYER]]", "NED", 0 }, -- New Zealand (NZL) -- {"[[PLAYER]]", "NZL", 0 }, -- Norway (NOR) -- {"[[PLAYER]]", "NOR", 0 }, -- Panama (PAN) -- {"[[PLAYER]]", "PAN", 0 }, -- Paraguay (PAR) -- {"[[PLAYER]]", "PAR", 0 }, -- Portugal (POR) -- {"[[PLAYER]]", "POR", 0 }, -- Qatar (QAT) -- {"[[PLAYER]]", "QAT", 0 }, -- Saudi Arabia (KSA) -- {"[[PLAYER]]", "KSA", 0 }, -- Scotland (SCO) -- {"[[PLAYER]]", "SCO", 0 }, -- Senegal (SEN) -- {"[[PLAYER]]", "SEN", 0 }, -- South Africa (RSA) -- {"[[PLAYER]]", "RSA", 0 }, -- South Korea (KOR) {"[[Hwang In-beom]]", "KOR", 1 }, {"[[Oh Hyeon-gyu]]", "KOR", 1 }, -- Spain (ESP) -- {"[[PLAYER]]", "ESP", 0 }, -- Sweden (SWE) -- {"[[PLAYER]]", "SWE", 0 }, -- Switzerland (SUI) -- {"[[PLAYER]]", "SUI", 0 }, -- Tunisia (TUN) -- {"[[PLAYER]]", "TUN", 0 }, -- Turkey (TUR) -- {"[[PLAYER]]", "TUR", 0 }, -- United States (USA) -- {"[[PLAYER]]", "USA", 0 }, -- Uruguay (URU) -- {"[[PLAYER]]", "URU", 0 }, -- Uzbekistan (UZB) -- {"[[PLAYER]]", "UZB", 0 }, } -- all competition own goal scorers data.owngoalscorers = { -- player wikilink, country, { own goals, "own goal opponents" } -- {"[[PLAYER]]", "CODE", { 1, "OPPONENT" } }, } return data km19isdel28tsxclmpnz6p7jako5lk5 मोड्युल:Goalscorers/data/Country codes 828 150526 1361443 2019-01-03T07:06:42Z en>Jts1882 0 create subpage with country code aliases (using list in [[Module:SportsRankings/data/FIFA World Rankings]]) 1361443 Scribunto text/plain local p = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "AIA", "Anguilla" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "ASA", "American Samoa" }, { "ATG", "Antigua and Barbuda" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BAN", "Bangladesh" }, { "BDI", "Burundi" }, { "BEL", "Belgium" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BFA", "Burkina Faso" }, { "BHR", "Bahrain" }, { "BHU", "Bhutan" }, { "BIH", "Bosnia and Herzegovina" }, { "BLR", "Belarus" }, { "BLZ", "Belize" }, { "BOL", "Bolivia" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "BRB", "Barbados" }, { "BRU", "Brunei Darussalam" }, { "BUL", "Bulgaria" }, { "CAM", "Cambodia" }, { "CAN", "Canada" }, { "CAY", "Cayman Islands" }, { "CGO", "Congo" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China PR" }, { "CIV", "Côte d'Ivoire" }, { "CMR", "Cameroon" }, { "COD", "Congo DR" }, { "COK", "Cook Islands" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CPV", "Cape Verde Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CTA", "Central African Republic" }, { "CUB", "Cuba" }, { "CUW", "Curaçao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "ESP", "Spain" }, { "EST", "Estonia" }, { "ETH", "Ethiopia" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "FRO", "Faroe Islands" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GNB", "Guinea-Bissau" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GUM", "Guam" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HKG", "Hong Kong" }, { "HON", "Honduras" }, { "HUN", "Hungary" }, { "IDN", "Indonesia" }, { "IND", "India" }, { "IRL", "Republic of Ireland" }, { "IRN", "IR Iran" }, { "IRQ", "Iraq" }, { "ISL", "Iceland" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "JAM", "Jamaica" }, { "JOR", "Jordan" }, { "JPN", "Japan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KGZ", "Kyrgyz Republic" }, { "KOR", "Korea Republic" }, { "KSA", "Saudi Arabia" }, { "KUW", "Kuwait" }, { "KVX", "Kosovo" }, { "LAO", "Laos" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LCA", "St. Lucia" }, { "LES", "Lesotho" }, { "LIB", "Lebanon" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "LVA", "Latvia" }, { "MAC", "Macau" }, { "MAD", "Madagascar" }, { "MAR", "Morocco" }, { "MAS", "Malaysia" }, { "MDA", "Moldova" }, { "MDV", "Maldives" }, { "MEX", "Mexico" }, { "MKD", "FYR Macedonia" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MNE", "Montenegro" }, { "MNG", "Mongolia" }, { "MOZ", "Mozambique" }, { "MRI", "Mauritius" }, { "MSR", "Montserrat" }, { "MTN", "Mauritania" }, { "MWI", "Malawi" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NCA", "Nicaragua" }, { "NCL", "New Caledonia" }, { "NED", "Netherlands" }, { "NEP", "Nepal" }, { "NGA", "Nigeria" }, { "NIG", "Niger" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "NZL", "New Zealand" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PAN", "Panama" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "PLE", "Palestine" }, { "PNG", "Papua New Guinea" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PRK", "Korea DPR" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "ROU", "Romania" }, { "RSA", "South Africa" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SAM", "Samoa" }, { "SCO", "Scotland" }, { "SDN", "Sudan" }, { "SEN", "Senegal" }, { "SEY", "Seychelles" }, { "SIN", "Singapore" }, { "SKN", "St. Kitts and Nevis" }, { "SLE", "Sierra Leone" }, { "SLV", "El Salvador" }, { "SMR", "San Marino" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "SRB", "Serbia" }, { "SRI", "Sri Lanka" }, { "SSD", "South Sudan" }, { "STP", "Sao Tome e Principe" }, { "SUI", "Switzerland" }, { "SUR", "Suriname" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SWE", "Sweden" }, { "SWZ", "Swaziland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TAN", "Tanzania" }, { "TCA", "Turks and Caicos Islands" }, { "TGA", "Tonga" }, { "THA", "Thailand" }, { "TJK", "Tajikistan" }, { "TKM", "Turkmenistan" }, { "TLS", "Timor-Leste" }, { "TOG", "Togo" }, { "TPE", "Chinese Taipei" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "UAE", "United Arab Emirates" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "URU", "Uruguay" }, { "USA", "USA" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VGB", "British Virgin Islands" }, { "VIE", "Vietnam" }, { "VIN", "St. Vincent / Grenadines" }, { "VIR", "US Virgin Islands" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, } return data j4gi4yh556ejci1uyco5t54sssdtspg 1361444 1361443 2019-01-03T08:41:39Z en>Jts1882 0 match variable name 1361444 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "AIA", "Anguilla" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "ASA", "American Samoa" }, { "ATG", "Antigua and Barbuda" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BAN", "Bangladesh" }, { "BDI", "Burundi" }, { "BEL", "Belgium" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BFA", "Burkina Faso" }, { "BHR", "Bahrain" }, { "BHU", "Bhutan" }, { "BIH", "Bosnia and Herzegovina" }, { "BLR", "Belarus" }, { "BLZ", "Belize" }, { "BOL", "Bolivia" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "BRB", "Barbados" }, { "BRU", "Brunei Darussalam" }, { "BUL", "Bulgaria" }, { "CAM", "Cambodia" }, { "CAN", "Canada" }, { "CAY", "Cayman Islands" }, { "CGO", "Congo" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China PR" }, { "CIV", "Côte d'Ivoire" }, { "CMR", "Cameroon" }, { "COD", "Congo DR" }, { "COK", "Cook Islands" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CPV", "Cape Verde Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CTA", "Central African Republic" }, { "CUB", "Cuba" }, { "CUW", "Curaçao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "ESP", "Spain" }, { "EST", "Estonia" }, { "ETH", "Ethiopia" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "FRO", "Faroe Islands" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GNB", "Guinea-Bissau" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GUM", "Guam" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HKG", "Hong Kong" }, { "HON", "Honduras" }, { "HUN", "Hungary" }, { "IDN", "Indonesia" }, { "IND", "India" }, { "IRL", "Republic of Ireland" }, { "IRN", "IR Iran" }, { "IRQ", "Iraq" }, { "ISL", "Iceland" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "JAM", "Jamaica" }, { "JOR", "Jordan" }, { "JPN", "Japan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KGZ", "Kyrgyz Republic" }, { "KOR", "Korea Republic" }, { "KSA", "Saudi Arabia" }, { "KUW", "Kuwait" }, { "KVX", "Kosovo" }, { "LAO", "Laos" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LCA", "St. Lucia" }, { "LES", "Lesotho" }, { "LIB", "Lebanon" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "LVA", "Latvia" }, { "MAC", "Macau" }, { "MAD", "Madagascar" }, { "MAR", "Morocco" }, { "MAS", "Malaysia" }, { "MDA", "Moldova" }, { "MDV", "Maldives" }, { "MEX", "Mexico" }, { "MKD", "FYR Macedonia" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MNE", "Montenegro" }, { "MNG", "Mongolia" }, { "MOZ", "Mozambique" }, { "MRI", "Mauritius" }, { "MSR", "Montserrat" }, { "MTN", "Mauritania" }, { "MWI", "Malawi" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NCA", "Nicaragua" }, { "NCL", "New Caledonia" }, { "NED", "Netherlands" }, { "NEP", "Nepal" }, { "NGA", "Nigeria" }, { "NIG", "Niger" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "NZL", "New Zealand" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PAN", "Panama" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "PLE", "Palestine" }, { "PNG", "Papua New Guinea" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PRK", "Korea DPR" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "ROU", "Romania" }, { "RSA", "South Africa" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SAM", "Samoa" }, { "SCO", "Scotland" }, { "SDN", "Sudan" }, { "SEN", "Senegal" }, { "SEY", "Seychelles" }, { "SIN", "Singapore" }, { "SKN", "St. Kitts and Nevis" }, { "SLE", "Sierra Leone" }, { "SLV", "El Salvador" }, { "SMR", "San Marino" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "SRB", "Serbia" }, { "SRI", "Sri Lanka" }, { "SSD", "South Sudan" }, { "STP", "Sao Tome e Principe" }, { "SUI", "Switzerland" }, { "SUR", "Suriname" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SWE", "Sweden" }, { "SWZ", "Swaziland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TAN", "Tanzania" }, { "TCA", "Turks and Caicos Islands" }, { "TGA", "Tonga" }, { "THA", "Thailand" }, { "TJK", "Tajikistan" }, { "TKM", "Turkmenistan" }, { "TLS", "Timor-Leste" }, { "TOG", "Togo" }, { "TPE", "Chinese Taipei" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "UAE", "United Arab Emirates" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "URU", "Uruguay" }, { "USA", "USA" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VGB", "British Virgin Islands" }, { "VIE", "Vietnam" }, { "VIN", "St. Vincent / Grenadines" }, { "VIR", "US Virgin Islands" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, } return data iziwm0og5evi84ck43hek2fltj1ww0v 1361445 1361444 2019-01-04T07:15:43Z en>S.A. Julio 0 adjust per wiki names 1361445 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China Pr" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KVX", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LIB", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "Macedonia" }, { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SIN", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, } return data c9wji2al8368j03hxfjx07jzwe1bv2p 1361446 1361445 2019-01-04T07:40:54Z en>S.A. Julio 0 add codes 1361446 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China Pr" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KVX", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LIB", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "Macedonia" }, { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SIN", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obselete names { "BGU", "British Guiana" }, { "BIN", "India" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "EIR", "Ireland" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine, British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data 343vss5m1tdkc3zpacgh6ue9qft1ras 1361447 1361446 2019-01-04T07:44:07Z en>S.A. Julio 0 adjust 1361447 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China Pr" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KVX", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LIB", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "Macedonia" }, { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SIN", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obselete names { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "MAL", "Malaya" }, { "PAL", "Mandatory Palestine" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data bddxxq7qdock6gjn22jfkhsdheyfa21 1361448 1361447 2019-01-04T07:47:55Z en>S.A. Julio 0 fix 1361448 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China Pr" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KVX", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LIB", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "Macedonia" }, { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SIN", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obselete names { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data 23d62tegqdbmq9zj8nyaois8nxmtgqo 1361449 1361448 2019-01-25T12:17:53Z en>S.A. Julio 0 add 1361449 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China Pr" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KVX", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LIB", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "Macedonia" }, { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SIN", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obselete names { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, { "FRY", "Fr Yugoslavia" }, -- unofficial but distinguishes from KSCS/SFRY -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data gacbf0dv99rf0l8o1982cbl2s44shv4 1361450 1361449 2019-02-13T16:04:41Z en>S.A. Julio 0 adjust 1361450 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China Pr" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, -- full name must be used for Swaziland (pre-2018) { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KVX", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LIB", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "North Macedonia" }, -- full name must be used for Macedonia (pre-2019) { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SIN", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obselete names { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, { "FRY", "Fr Yugoslavia" }, -- unofficial but distinguishes from KSCS/SFRY -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data 9qawm1ei8w8ob7cpe2rghg9p9zgqrqt 1361451 1361450 2019-03-08T17:07:56Z en>S.A. Julio 0 add 1361451 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China Pr" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, -- full name must be used for Swaziland (pre-2018) { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KVX", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LIB", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "North Macedonia" }, -- for Republic of North Macedonia (2019 and later) { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SIN", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obselete names { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, { "FRY", "Fr Yugoslavia" }, -- unofficial but distinguishes from KSCS/SFRY { "RMK", "Macedonia" }, -- for Republic of Macedonia (pre-2019) -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data 1rmj4zhl8xbfn8k20m7eyacwknolutx 1361452 1361451 2021-06-05T11:17:15Z en>Centaur271188 0 fix Lebanon 1361452 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China Pr" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, -- full name must be used for Swaziland (pre-2018) { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KVX", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LBN", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "North Macedonia" }, -- for Republic of North Macedonia (2019 and later) { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SIN", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obselete names { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, { "FRY", "Fr Yugoslavia" }, -- unofficial but distinguishes from KSCS/SFRY { "RMK", "Macedonia" }, -- for Republic of Macedonia (pre-2019) -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data sei1c8mh90puagr8ih69ibnr6aaeaq8 1361453 1361452 2022-09-23T19:19:20Z en>S.A. Julio 0 update 1361453 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, -- full name must be used for Swaziland (pre-2018) { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KOS", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LBN", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "North Macedonia" }, -- for Republic of North Macedonia (2019 and later) { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SIN", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obselete names { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "KVX", "Kosovo" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, { "FRY", "Fr Yugoslavia" }, -- unofficial but distinguishes from KSCS/SFRY { "RMK", "Macedonia" }, -- for Republic of Macedonia (pre-2019) -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data eofvxghfhgmkks00kp0qv0aykpvcfto 1361454 1361453 2024-03-28T13:05:46Z en>Centaur271188 0 update country code 1361454 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, -- full name must be used for Swaziland (pre-2018) { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KOS", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LBN", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "North Macedonia" }, -- for Republic of North Macedonia (2019 and later) { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SGP", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obselete names { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "KVX", "Kosovo" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, { "FRY", "Fr Yugoslavia" }, -- unofficial but distinguishes from KSCS/SFRY { "RMK", "Macedonia" }, -- for Republic of Macedonia (pre-2019) -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data e8u1q7adu6eu90y6i8e5ta8b64s6bmw 1361455 1361454 2024-04-27T15:53:40Z en>Wburrow 0 Adding SIN and LIB to obsolete codes 1361455 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, -- full name must be used for Swaziland (pre-2018) { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KOS", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LBN", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "North Macedonia" }, -- for Republic of North Macedonia (2019 and later) { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SGP", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obsolete names/codes { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "KVX", "Kosovo" }, { "LIB", "Lebanon" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SIN", "Singapore" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, { "FRY", "Fr Yugoslavia" }, -- unofficial but distinguishes from KSCS/SFRY { "RMK", "Macedonia" }, -- for Republic of Macedonia (pre-2019) -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data 0bd8p1y1pz4xotozqlkuzrzrx5npz7t 1361456 1361455 2025-03-21T18:00:46Z en>MusikBot II 0 Protected "[[Module:Goalscorers/data/Country codes]]": [[Wikipedia:High-risk templates|High-risk template or module]]: 250 transclusions ([[User:MusikBot II/TemplateProtector|more info]]) ([Edit=Require autoconfirmed or confirmed access] (indefinite)) 1361455 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, -- full name must be used for Swaziland (pre-2018) { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KOS", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LBN", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "North Macedonia" }, -- for Republic of North Macedonia (2019 and later) { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SGP", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obsolete names/codes { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "KVX", "Kosovo" }, { "LIB", "Lebanon" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SIN", "Singapore" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, { "FRY", "Fr Yugoslavia" }, -- unofficial but distinguishes from KSCS/SFRY { "RMK", "Macedonia" }, -- for Republic of Macedonia (pre-2019) -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data 0bd8p1y1pz4xotozqlkuzrzrx5npz7t 1361457 1361456 2026-06-12T08:18:57Z पर्वत सुवेदी 31224 [[:en:Module:Goalscorers/data/Country_codes]] बाट १४ संशोधन(हरू) 1361455 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, -- full name must be used for Swaziland (pre-2018) { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KOS", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LBN", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "North Macedonia" }, -- for Republic of North Macedonia (2019 and later) { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SGP", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "South Korea" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obsolete names/codes { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "KVX", "Kosovo" }, { "LIB", "Lebanon" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SIN", "Singapore" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, { "FRY", "Fr Yugoslavia" }, -- unofficial but distinguishes from KSCS/SFRY { "RMK", "Macedonia" }, -- for Republic of Macedonia (pre-2019) -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data 0bd8p1y1pz4xotozqlkuzrzrx5npz7t 1361459 1361457 2026-06-12T08:24:16Z पर्वत सुवेदी 31224 1361459 Scribunto text/plain local data = {} -- list of FIFA country codes data.alias = { { "AFG", "Afghanistan" }, { "ALB", "Albania" }, { "ALG", "Algeria" }, { "ASA", "American Samoa" }, { "AND", "Andorra" }, { "ANG", "Angola" }, { "AIA", "Anguilla" }, { "ATG", "Antigua and Barbuda" }, { "ARG", "Argentina" }, { "ARM", "Armenia" }, { "ARU", "Aruba" }, { "AUS", "Australia" }, { "AUT", "Austria" }, { "AZE", "Azerbaijan" }, { "BAH", "Bahamas" }, { "BHR", "Bahrain" }, { "BAN", "Bangladesh" }, { "BRB", "Barbados" }, { "BLR", "Belarus" }, { "BEL", "Belgium" }, { "BLZ", "Belize" }, { "BEN", "Benin" }, { "BER", "Bermuda" }, { "BHU", "Bhutan" }, { "BOL", "Bolivia" }, { "BIH", "Bosnia and Herzegovina" }, { "BOT", "Botswana" }, { "BRA", "Brazil" }, { "VGB", "British Virgin Islands" }, { "BRU", "Brunei" }, { "BUL", "Bulgaria" }, { "BFA", "Burkina Faso" }, { "BDI", "Burundi" }, { "CAM", "Cambodia" }, { "CMR", "Cameroon" }, { "CAN", "Canada" }, { "CPV", "Cape Verde" }, { "CAY", "Cayman Islands" }, { "CTA", "Central African Republic" }, { "CHA", "Chad" }, { "CHI", "Chile" }, { "CHN", "China" }, { "TPE", "Chinese Taipei" }, { "COL", "Colombia" }, { "COM", "Comoros" }, { "CGO", "Congo" }, { "COK", "Cook Islands" }, { "CRC", "Costa Rica" }, { "CRO", "Croatia" }, { "CUB", "Cuba" }, { "CUW", "Curacao" }, { "CYP", "Cyprus" }, { "CZE", "Czech Republic" }, { "DEN", "Denmark" }, { "DJI", "Djibouti" }, { "DMA", "Dominica" }, { "DOM", "Dominican Republic" }, { "COD", "Dr Congo" }, { "ECU", "Ecuador" }, { "EGY", "Egypt" }, { "SLV", "El Salvador" }, { "ENG", "England" }, { "EQG", "Equatorial Guinea" }, { "ERI", "Eritrea" }, { "EST", "Estonia" }, { "SWZ", "Eswatini" }, -- full name must be used for Swaziland (pre-2018) { "ETH", "Ethiopia" }, { "FRO", "Faroe Islands" }, { "FIJ", "Fiji" }, { "FIN", "Finland" }, { "FRA", "France" }, { "GAB", "Gabon" }, { "GAM", "Gambia" }, { "GEO", "Georgia" }, { "GER", "Germany" }, { "GHA", "Ghana" }, { "GIB", "Gibraltar" }, { "GRE", "Greece" }, { "GRN", "Grenada" }, { "GUM", "Guam" }, { "GUA", "Guatemala" }, { "GUI", "Guinea" }, { "GNB", "Guineabissau" }, { "GUY", "Guyana" }, { "HAI", "Haiti" }, { "HON", "Honduras" }, { "HKG", "Hong Kong" }, { "HUN", "Hungary" }, { "ISL", "Iceland" }, { "IND", "India" }, { "IDN", "Indonesia" }, { "IRN", "Iran" }, { "IRQ", "Iraq" }, { "ISR", "Israel" }, { "ITA", "Italy" }, { "CIV", "Ivory Coast" }, { "JAM", "Jamaica" }, { "JPN", "Japan" }, { "JOR", "Jordan" }, { "KAZ", "Kazakhstan" }, { "KEN", "Kenya" }, { "KOS", "Kosovo" }, { "KUW", "Kuwait" }, { "KGZ", "Kyrgyzstan" }, { "LAO", "Laos" }, { "LVA", "Latvia" }, { "LBN", "Lebanon" }, { "LES", "Lesotho" }, { "LBR", "Liberia" }, { "LBY", "Libya" }, { "LIE", "Liechtenstein" }, { "LTU", "Lithuania" }, { "LUX", "Luxembourg" }, { "MAC", "Macau" }, { "MKD", "North Macedonia" }, -- for Republic of North Macedonia (2019 and later) { "MAD", "Madagascar" }, { "MWI", "Malawi" }, { "MAS", "Malaysia" }, { "MDV", "Maldives" }, { "MLI", "Mali" }, { "MLT", "Malta" }, { "MTN", "Mauritania" }, { "MRI", "Mauritius" }, { "MEX", "Mexico" }, { "MDA", "Moldova" }, { "MNG", "Mongolia" }, { "MNE", "Montenegro" }, { "MSR", "Montserrat" }, { "MAR", "Morocco" }, { "MOZ", "Mozambique" }, { "MYA", "Myanmar" }, { "NAM", "Namibia" }, { "NEP", "Nepal" }, { "NED", "Netherlands" }, { "NCL", "New Caledonia" }, { "NZL", "New Zealand" }, { "NCA", "Nicaragua" }, { "NIG", "Niger" }, { "NGA", "Nigeria" }, { "PRK", "North Korea" }, { "NIR", "Northern Ireland" }, { "NOR", "Norway" }, { "OMA", "Oman" }, { "PAK", "Pakistan" }, { "PLE", "Palestine" }, { "PAN", "Panama" }, { "PNG", "Papua New Guinea" }, { "PAR", "Paraguay" }, { "PER", "Peru" }, { "PHI", "Philippines" }, { "POL", "Poland" }, { "POR", "Portugal" }, { "PUR", "Puerto Rico" }, { "QAT", "Qatar" }, { "IRL", "Republic of Ireland" }, { "ROU", "Romania" }, { "RUS", "Russia" }, { "RWA", "Rwanda" }, { "SKN", "Saint Kitts and Nevis" }, { "LCA", "Saint Lucia" }, { "VIN", "Saint Vincent and the Grenadines" }, { "SAM", "Samoa" }, { "SMR", "San Marino" }, { "STP", "Sao Tome and Principe" }, { "KSA", "Saudi Arabia" }, { "SCO", "Scotland" }, { "SEN", "Senegal" }, { "SRB", "Serbia" }, { "SEY", "Seychelles" }, { "SLE", "Sierra Leone" }, { "SGP", "Singapore" }, { "SVK", "Slovakia" }, { "SVN", "Slovenia" }, { "SOL", "Solomon Islands" }, { "SOM", "Somalia" }, { "RSA", "South Africa" }, { "KOR", "दक्षिण कोरिया" }, { "SSD", "South Sudan" }, { "ESP", "Spain" }, { "SRI", "Sri Lanka" }, { "SDN", "Sudan" }, { "SUR", "Suriname" }, { "SWE", "Sweden" }, { "SUI", "Switzerland" }, { "SYR", "Syria" }, { "TAH", "Tahiti" }, { "TJK", "Tajikistan" }, { "TAN", "Tanzania" }, { "THA", "Thailand" }, { "TLS", "Timorleste" }, { "TOG", "Togo" }, { "TGA", "Tonga" }, { "TRI", "Trinidad and Tobago" }, { "TUN", "Tunisia" }, { "TUR", "Turkey" }, { "TKM", "Turkmenistan" }, { "TCA", "Turks and Caicos Islands" }, { "UGA", "Uganda" }, { "UKR", "Ukraine" }, { "UAE", "United Arab Emirates" }, { "USA", "United States" }, { "URU", "Uruguay" }, { "VIR", "Us Virgin Islands" }, { "UZB", "Uzbekistan" }, { "VAN", "Vanuatu" }, { "VEN", "Venezuela" }, { "VIE", "Vietnam" }, { "WAL", "Wales" }, { "YEM", "Yemen" }, { "ZAM", "Zambia" }, { "ZIM", "Zimbabwe" }, -- Former countries and obsolete names/codes { "BGU", "British Guiana" }, { "BOH", "Bohemia" }, { "BUR", "Burma" }, { "CAF", "Central African Republic" }, { "CEY", "Ceylon" }, { "CIS", "Cis" }, { "TCH", "Czechoslovakia" }, { "DAH", "Dahomey" }, { "INH", "Dutch East Indies" }, { "GDR", "East Germany" }, { "GOC", "Gold Coast" }, { "BIN", "India" }, { "EIR", "Ireland" }, { "KVX", "Kosovo" }, { "LIB", "Lebanon" }, { "MAL", "Malaya" }, { "ANT", "Netherlands Antilles" }, { "HOL", "Netherlands" }, { "HEB", "New Hebrides" }, { "VNO", "North Vietnam" }, { "NYE", "North Yemen" }, { "NRH", "Northern Rhodesia" }, { "PAL", "Palestine British Mandate" }, { "ROM", "Romania" }, { "RHO", "Rhodesia" }, { "SAA", "Saar" }, { "SCG", "Serbia and Montenegro" }, { "SIA", "Siam" }, { "SIN", "Singapore" }, { "SRH", "Southern Rhodesia" }, { "VSO", "South Vietnam" }, { "SYE", "South Yemen" }, { "URS", "Soviet Union" }, { "SUD", "Sudan" }, { "NGY", "Suriname" }, { "TAA", "Tanganyika" }, { "TAI", "Taiwan" }, { "UAR", "United Arab Republic" }, { "UPV", "Upper Volta" }, { "FRG", "West Germany" }, { "WSM", "Western Samoa" }, { "YUG", "Yugoslavia" }, { "ZAI", "Zaire" }, { "FRY", "Fr Yugoslavia" }, -- unofficial but distinguishes from KSCS/SFRY { "RMK", "Macedonia" }, -- for Republic of Macedonia (pre-2019) -- Affiliated to FIFA confederations { "BOE", "Bonaire" }, { "GUF", "French Guiana" }, { "GLP", "Guadeloupe" }, { "KIR", "Kiribati" }, { "MTQ", "Martinique" }, { "NIU", "Niue" }, { "NMI", "Northern Mariana Islands" }, { "REU", "Reunion" }, { "SMN", "Saint Martin" }, { "SMA", "Sint Maarten" }, { "TUV", "Tuvalu" }, { "ZAN", "Zanzibar" }, } return data h0zg1pj653uju58j2en6nvhxci4u8eq 1361460 1361459 2026-06-12T08:37:42Z पर्वत सुवेदी 31224 1361460 Scribunto text/plain local data = {} -- फिफा देश कोडहरूको सूची data.alias = { { "AFG", "अफगानिस्तान" }, { "ALB", "अल्बानिया" }, { "ALG", "अल्जेरिया" }, { "ASA", "अमेरिकी सामोआ" }, { "AND", "एन्डोरा" }, { "ANG", "अङ्गोला" }, { "AIA", "एङ्गुइला" }, { "ATG", "एन्टिगुवा र बर्बुडा" }, { "ARG", "अर्जेन्टिना" }, { "ARM", "आर्मेनिया" }, { "ARU", "अरुबा" }, { "AUS", "अस्ट्रेलिया" }, { "AUT", "अस्ट्रिया" }, { "AZE", "अजरबैजान" }, { "BAH", "बहामस" }, { "BHR", "बहराइन" }, { "BAN", "बङ्गलादेश" }, { "BRB", "बार्बाडोस" }, { "BLR", "बेलारुस" }, { "BEL", "बेल्जियम" }, { "BLZ", "बेलिज" }, { "BEN", "बेनिन" }, { "BER", "बर्मुडा" }, { "BHU", "भुटान" }, { "BOL", "बोलिभिया" }, { "BIH", "बोस्निया र हर्जगोभिना" }, { "BOT", "बोत्स्वाना" }, { "BRA", "ब्राजिल" }, { "VGB", "ब्रिटिस भर्जिन टापुहरू" }, { "BRU", "ब्रुनाई" }, { "BUL", "बुल्गेरिया" }, { "BFA", "बुर्किना फासो" }, { "BDI", "बुरुन्डी" }, { "CAM", "कम्बोडिया" }, { "CMR", "क्यामरुन" }, { "CAN", "क्यानडा" }, { "CPV", "केप भर्ड" }, { "CAY", "केम्यान टापु" }, { "CTA", "मध्य अफ्रिकी गणतन्त्र" }, { "CHA", "चाड" }, { "CHI", "चिली" }, { "CHN", "चीन" }, { "TPE", "चिनियाँ ताइपेई" }, { "COL", "कोलम्बिया" }, { "COM", "कोमोरोस" }, { "CGO", "कङ्गो" }, { "COK", "कुक टापु" }, { "CRC", "कोस्टारिका" }, { "CRO", "क्रोएसिया" }, { "CUB", "क्युबा" }, { "CUW", "कुरासाओ" }, { "CYP", "साइप्रस" }, { "CZE", "चेक गणतन्त्र" }, { "DEN", "डेनमार्क" }, { "DJI", "जिबुटी" }, { "DMA", "डोमिनिका" }, { "DOM", "डोमिनिकन गणतन्त्र" }, { "COD", "प्रजातान्त्रिक गणतन्त्र कङ्गो" }, { "ECU", "इक्वेडर" }, { "EGY", "इजिप्ट" }, { "SLV", "एल साल्भाडोर" }, { "ENG", "इङ्ल्यान्ड" }, { "EQG", "भुमध्यरेखीय गिनी" }, { "ERI", "इरित्रिया" }, { "EST", "एस्टोनिया" }, { "SWZ", "इस्वातिनी" }, -- सन् २०१८ भन्दा अघिको स्वाजिल्यान्डको लागि पूरा नाम प्रयोग गर्नुपर्छ { "ETH", "इथियोपिया" }, { "FRO", "फ्यारो टापु" }, { "FIJ", "फिजी" }, { "FIN", "फिनल्यान्ड" }, { "FRA", "फ्रान्स" }, { "GAB", "गाबोन" }, { "GAM", "गाम्बिया" }, { "GEO", "जर्जिया" }, { "GER", "जर्मनी" }, { "GHA", "घाना" }, { "GIB", "जिब्राल्टर" }, { "GRE", "गिस" }, { "GRN", "ग्रेनाडा" }, { "GUM", "ग्वाम" }, { "GUA", "ग्वाटेमाला" }, { "GUI", "गिनी" }, { "GNB", "गिनी-बिसाउ" }, { "GUY", "गुयाना" }, { "HAI", "हाइटी" }, { "HON", "होन्डुरस" }, { "HKG", "हङकङ" }, { "HUN", "हङ्गेरी" }, { "ISL", "आइसल्यान्ड" }, { "IND", "भारत" }, { "IDN", "इन्डोनेसिया" }, { "IRN", "इरान" }, { "IRQ", "इराक" }, { "ISR", "इजरायल" }, { "ITA", "इटाली" }, { "CIV", "आइभोरी कोस्ट" }, { "JAM", "जमैका" }, { "JPN", "जापान" }, { "JOR", "जोर्डन" }, { "KAZ", "कजाख्स्तान" }, { "KEN", "केन्या" }, { "KOS", "कोसोभो" }, { "KUW", "कुवेत" }, { "KGZ", "किर्गिस्तान" }, { "LAO", "लाओस" }, { "LVA", "लातभिया" }, { "LBN", "लेबनान" }, { "LES", "लेसोथो" }, { "LBR", "लाइबेरिया" }, { "LBY", "लिबिया" }, { "LIE", "लिस्टेनस्टाइन" }, { "LTU", "लिथुआनिया" }, { "LUX", "लक्जेम्बर्ग" }, { "MAC", "मकाउ" }, { "MKD", "उत्तर म्यासेडोनिया" }, -- उत्तर म्यासेडोनिया गणतन्त्रका लागि (सन् २०१९ र पछि) { "MAD", "मेडागास्कर" }, { "MWI", "मलावी" }, { "MAS", "मलेसिया" }, { "MDV", "माल्दिभ्स" }, { "MLI", "माली" }, { "MLT", "माल्टा" }, { "MTN", "मौरिटानिया" }, { "MRI", "मौरिसस" }, { "MEX", "मेक्सिको" }, { "MDA", "मोल्दोभा" }, { "MNG", "मङ्गोलिया" }, { "MNE", "मोन्टेनेग्रो" }, { "MSR", "मोन्टसेराट" }, { "MAR", "मोरक्को" }, { "MOZ", "मोजाम्बिक" }, { "MYA", "म्यानमार" }, { "NAM", "नामिबिया" }, { "NEP", "नेपाल" }, { "NED", "नेदरल्यान्ड" }, { "NCL", "नयाँ क्यालेडोनिया" }, { "NZL", "न्युजिल्यान्ड" }, { "NCA", "निकाराग्वा" }, { "NIG", "नाइजर" }, { "NGA", "नाइजेरिया" }, { "PRK", "उत्तर कोरिया" }, { "NIR", "उत्तरी आयरल्यान्ड" }, { "NOR", "नर्वे" }, { "OMA", "ओमान" }, { "PAK", "पाकिस्तान" }, { "PLE", "प्यालेस्टाइन" }, { "PAN", "पानामा" }, { "PNG", "पापुआ न्युगिनी" }, { "PAR", "पाराग्वे" }, { "PER", "पेरु" }, { "PHI", "फिलिपिन्स" }, { "POL", "पोल्यान्ड" }, { "POR", "पोर्चुगल" }, { "PUR", "पोर्तो रिको" }, { "QAT", "कतार" }, { "IRL", "गणतन्त्र आयरल्यान्ड" }, { "ROU", "रोमानिया" }, { "RUS", "रूस" }, { "RWA", "रुवान्डा" }, { "SKN", "सेन्ट किट्स र नेभिस" }, { "LCA", "सेन्ट लुसिया" }, { "VIN", "सेन्ट भिन्सेन्ट र ग्रेनाडिन्स" }, { "SAM", "सामोआ" }, { "SMR", "सान मारिनो" }, { "STP", "साओ टोमे र प्रिन्सिपे" }, { "KSA", "साउदी अरब" }, { "SCO", "स्कटल्यान्ड" }, { "SEN", "सेनेगल" }, { "SRB", "सर्बिया" }, { "SEY", "सेसेल्स" }, { "SLE", "सिएरा लियोन" }, { "SGP", "सिङ्गापुर" }, { "SVK", "स्लोभाकिया" }, { "SVN", "स्लोभेनिया" }, { "SOL", "सोलोमन टापु" }, { "SOM", "सोमालिया" }, { "RSA", "दक्षिण अफ्रिका" }, { "KOR", "दक्षिण कोरिया" }, { "SSD", "दक्षिण सुडान" }, { "ESP", "स्पेन" }, { "SRI", "श्रीलङ्का" }, { "SDN", "सुडान" }, { "SUR", "सुरिनाम" }, { "SWE", "स्वीडेन" }, { "SUI", "स्विट्जरल्यान्ड" }, { "SYR", "सिरिया" }, { "TAH", "ताहिती" }, { "TJK", "ताजिकिस्तान" }, { "TAN", "तान्जानिया" }, { "THA", "थाइल्यान्ड" }, { "TLS", "पूर्वी टिमोर" }, { "TOG", "टोगो" }, { "TGA", "टोङ्गा" }, { "TRI", "ट्रिनिडाड र टोबागो" }, { "TUN", "ट्युनिसिया" }, { "TUR", "टर्की" }, { "TKM", "तुर्कमेनिस्तान" }, { "TCA", "तुर्क्स र काइकोस टापु" }, { "UGA", "युगान्डा" }, { "UKR", "युक्रेन" }, { "UAE", "संयुक्त अरब इमिरेट्स" }, { "USA", "संयुक्त राज्य अमेरिका" }, { "URU", "उरुग्वे" }, { "VIR", "युएस भर्जिन टापु" }, { "UZB", "उज्बेकिस्तान" }, { "VAN", "भानुअटु" }, { "VEN", "भेनेजुएला" }, { "VIE", "भियतनाम" }, { "WAL", "वेल्स" }, { "YEM", "यमन" }, { "ZAM", "जाम्बिया" }, { "ZIM", "जिम्बाब्वे" }, -- भूतपूर्व देशहरू र पुराना नाम/कोडहरू { "BGU", "ब्रिटिस गुयाना" }, { "BOH", "बोहेमिया" }, { "BUR", "बर्मा" }, { "CAF", "केन्द्रीय अफ्रिकी गणतन्त्र" }, { "CEY", "सिलोन" }, { "CIS", "स्वतन्त्र राज्यहरूको राष्ट्रमण्डल" }, { "TCH", "चेकोस्लोभाकिया" }, { "DAH", "दाहोमी" }, { "INH", "डच इस्ट इन्डिज" }, { "GDR", "पूर्वी जर्मनी" }, { "GOC", "गोल्ड कोस्ट" }, { "BIN", "भारत" }, { "EIR", "आयरल्यान्ड" }, { "KVX", "कोसोभो" }, { "LIB", "लेबनान" }, { "MAL", "मलाया" }, { "ANT", "नेदरल्यान्ड्स एन्टिलीस" }, { "HOL", "नेदरल्यान्ड्स" }, { "HEB", "नयाँ हेब्राइड्स" }, { "VNO", "उत्तर भियतनाम" }, { "NYE", "उत्तर यमन" }, { "NRH", "उत्तरी रोडेसिया" }, { "PAL", "प्यालेस्टाइन ब्रिटिस म्यान्डेट" }, { "ROM", "रोमानिया" }, { "RHO", "रोडेसिया" }, { "SAA", "सार" }, { "SCG", "सर्बिया र मोन्टेनेग्रो" }, { "SIA", "स्याम" }, { "SIN", "सिंगापुर" }, { "SRH", "दक्षिणी रोडेसिया" }, { "VSO", "दक्षिण भियतनाम" }, { "SYE", "दक्षिण यमन" }, { "URS", "सोभियत सङ्घ" }, { "SUD", "सुडान" }, { "NGY", "सुरिनाम" }, { "TAA", "ताङ्गानिका" }, { "TAI", "ताइवान" }, { "UAR", "संयुक्त अरब गणतन्त्र" }, { "UPV", "अपर भोल्टा" }, { "FRG", "पश्चिम जर्मनी" }, { "WSM", "पश्चिमी सामोआ" }, { "YUG", "युगोस्लाभिया" }, { "ZAI", "जाइरे" }, { "FRY", "सङ्घीय युगोस्लाभिया" }, -- अनौपचारिक तर KSCS/SFRY बाट फरक छुट्याउन { "RMK", "म्यासेडोनिया" }, -- म्यासेडोनिया गणतन्त्रका लागि (सन् २०१९ भन्दा अघि) -- फिफा महासङ्घहरूसँग आबद्ध { "BOE", "बोनेयर" }, { "GUF", "फ्रेन्च गुयाना" }, { "GLP", "ग्वाडेलोप" }, { "KIR", "किरिबाती" }, { "MTQ", "मार्टिनिक" }, { "NIU", "निउए" }, { "NMI", "उत्तरी मारियाना टापुहरू" }, { "REU", "रियुनियन" }, { "SMN", "सेन्ट मार्टिन" }, { "SMA", "सिन्ट मार्टिन" }, { "TUV", "तुभालु" }, { "ZAN", "जान्जीबार" }, } return data ir8zth5lw0qshoflmh38o4pwdsoftag