Implemented new victory modal design.
After ![]() (image error) Size: 1.2 KiB |
BIN
app/assets/images/common/button-background-success-active.png
Normal file
After ![]() (image error) Size: 1.4 KiB |
After ![]() (image error) Size: 1.3 KiB |
BIN
app/assets/images/common/button-background-success-inactive.png
Normal file
After ![]() (image error) Size: 1.5 KiB |
After ![]() (image error) Size: 1.3 KiB |
BIN
app/assets/images/common/button-background-success-pressed.png
Normal file
After ![]() (image error) Size: 1.5 KiB |
Before ![]() (image error) Size: 9.1 KiB |
BIN
app/assets/images/pages/play/level/modal/victory_hero.png
Normal file
After ![]() (image error) Size: 34 KiB |
Before ![]() (image error) Size: 15 KiB After ![]() (image error) Size: 82 KiB ![]() ![]() |
Before ![]() (image error) Size: 13 KiB |
After ![]() (image error) Size: 76 KiB |
BIN
app/assets/images/pages/play/level/modal/victory_modal_shelf.png
Normal file
After ![]() (image error) Size: 3.8 KiB |
Before ![]() (image error) Size: 9 KiB After ![]() (image error) Size: 17 KiB ![]() ![]() |
BIN
app/assets/images/pages/play/level/modal/xp_gems_parchment.png
Normal file
After ![]() (image error) Size: 10 KiB |
|
@ -222,6 +222,7 @@
|
|||
reload_title: "Reload All Code?"
|
||||
reload_really: "Are you sure you want to reload this level back to the beginning?"
|
||||
reload_confirm: "Reload All"
|
||||
victory: "Victory"
|
||||
victory_title_prefix: ""
|
||||
victory_title_suffix: " Complete"
|
||||
victory_sign_up: "Sign Up to Save Progress"
|
||||
|
@ -234,6 +235,8 @@
|
|||
victory_review: "Tell us more!" # Only in old-style levels.
|
||||
victory_hour_of_code_done: "Are You Done?"
|
||||
victory_hour_of_code_done_yes: "Yes, I'm finished with my Hour of Code™!"
|
||||
victory_experience_gained: "XP Gained"
|
||||
victory_gems_gained: "Gems Gained"
|
||||
guide_title: "Guide"
|
||||
tome_minion_spells: "Your Minions' Spells" # Only in old-style levels.
|
||||
tome_read_only_spells: "Read-Only Spells" # Only in old-style levels.
|
||||
|
|
|
@ -253,13 +253,19 @@ kbd
|
|||
border-image-source: url(/images/common/button-background-primary-active-border.png)
|
||||
&.btn-success
|
||||
border-image-source: url(/images/common/button-background-success-active-border.png)
|
||||
color: darken(white, 5%)
|
||||
&.btn-warning
|
||||
border-image-source: url(/images/common/button-background-warning-active-border.png)
|
||||
color: darken(white, 5%)
|
||||
&.btn-danger
|
||||
border-image-source: url(/images/common/button-background-danger-active-border.png)
|
||||
|
||||
&:hover
|
||||
color: lighten(rgb(248, 197, 146), 5%)
|
||||
&.btn-success
|
||||
color: white
|
||||
&.btn-warning
|
||||
color: white
|
||||
|
||||
&:active
|
||||
&.btn-lg
|
||||
|
|
|
@ -2,55 +2,89 @@
|
|||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
#hero-victory-modal
|
||||
$hero-yellow-text: rgb(252, 201, 53)
|
||||
|
||||
//- Top-level modal container
|
||||
.modal-dialog
|
||||
margin-top: 15px
|
||||
margin-top: 0
|
||||
padding-top: 0
|
||||
width: 750px
|
||||
|
||||
.modal-content
|
||||
position: relative
|
||||
margin-top: -251px
|
||||
|
||||
&.full-achievements
|
||||
@media only screen and (max-height: 720px)
|
||||
.modal-dialog
|
||||
margin-top: -76px
|
||||
#victory-header
|
||||
background: transparent
|
||||
@media only screen and (max-height: 640px)
|
||||
.modal-dialog
|
||||
margin-top: -130px
|
||||
#victory-header
|
||||
display: none
|
||||
|
||||
//- Header
|
||||
|
||||
.background-wrapper
|
||||
//background: url("/images/pages/play/level/modal/victory_modal_background.png")
|
||||
width: 550px
|
||||
background-color: transparent
|
||||
width: 750px
|
||||
background: transparent
|
||||
border: 0px solid transparent
|
||||
border-width: 25px
|
||||
border-image: url("/images/pages/play/level/modal/victory_modal_background.png") 25 fill round
|
||||
border-image: url("/images/pages/play/level/modal/victory_modal_border_background.png") 250 0 100 0 fill round
|
||||
border-width: 250px 0 100px 0
|
||||
border-radius: 12px
|
||||
|
||||
#victory-banner
|
||||
position: absolute
|
||||
left: -30px
|
||||
z-index: 0
|
||||
|
||||
#victory-header
|
||||
position: absolute
|
||||
left: 135px
|
||||
display: block
|
||||
margin: 10px auto 0
|
||||
// http://easings.net/#easeOutBack plus tweaked a bit: http://cubic-bezier.com/#.18,.68,.75,2
|
||||
@include transition(0.5s cubic-bezier(0.18, 0.68, 0.75, 2))
|
||||
z-index: 1
|
||||
|
||||
&.out
|
||||
@include scale(0)
|
||||
|
||||
.modal-header
|
||||
height: 85px
|
||||
border: none
|
||||
position: absolute
|
||||
left: 188px
|
||||
width: 378px
|
||||
height: 134px
|
||||
margin: 0
|
||||
padding: 0
|
||||
|
||||
#victory-header
|
||||
position: relative
|
||||
// http://easings.net/#easeOutBack plus tweaked a bit: http://cubic-bezier.com/#.18,.68,.75,2
|
||||
@include transition(0.5s cubic-bezier(0.18, 0.68, 0.75, 2))
|
||||
z-index: 1
|
||||
width: 100%
|
||||
height: 100%
|
||||
text-align: center
|
||||
background: transparent url(/images/pages/play/level/modal/victory_hero.png/) no-repeat
|
||||
background-position: center -88px
|
||||
|
||||
&.out
|
||||
@include scale(0)
|
||||
|
||||
#victory-title
|
||||
display: inline-block
|
||||
margin-top: 74px
|
||||
|
||||
h1
|
||||
text-transform: uppercase
|
||||
text-align: center
|
||||
color: $hero-yellow-text
|
||||
font-size: 80px
|
||||
margin: 0
|
||||
padding: 0
|
||||
text-shadow: black 8px 8px 0, black -8px -8px 0, black 8px -8px 0, black -8px 8px 0, black 8px 0px 0, black 0px -8px 0, black -8px 0px 0, black 0px 8px 0
|
||||
|
||||
//- Achievement panels
|
||||
|
||||
.modal-body
|
||||
padding: 0 20px
|
||||
min-height: 30px
|
||||
margin-top: 160px
|
||||
|
||||
.achievement-panel
|
||||
background: url("/images/pages/play/level/modal/achievement_plate.png")
|
||||
width: 451px
|
||||
height: 144px
|
||||
margin: 5px auto
|
||||
background: transparent url("/images/pages/play/level/modal/victory_modal_shelf.png") no-repeat center 73px
|
||||
width: 824px
|
||||
height: 127px
|
||||
margin: 0px -37px 0px -57px
|
||||
position: relative
|
||||
|
||||
@include transition-duration(1s)
|
||||
|
@ -71,12 +105,16 @@
|
|||
|
||||
.achievement-description
|
||||
@include opacity(0.75)
|
||||
z-index: 1
|
||||
position: absolute
|
||||
text-align: center
|
||||
left: 95px
|
||||
right: 98px
|
||||
top: 10px
|
||||
color: white
|
||||
top: 86px
|
||||
color: $hero-yellow-text
|
||||
font-weight: bold
|
||||
text-transform: uppercase
|
||||
font-family: 'Open Sans Condensed'
|
||||
white-space: nowrap
|
||||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
|
@ -85,8 +123,7 @@
|
|||
position: absolute
|
||||
left: 25px
|
||||
right: 23px
|
||||
top: 41px
|
||||
bottom: 18px
|
||||
top: 0
|
||||
@include flexbox()
|
||||
@include flex-justify-center()
|
||||
|
||||
|
@ -102,7 +139,7 @@
|
|||
z-index: 1
|
||||
@include transition(0.25s ease)
|
||||
|
||||
&.hero, &.item
|
||||
&.hero, &.item, &.xp, &.gems
|
||||
background: url("/images/pages/play/level/modal/reward_plate_wide.png")
|
||||
width: 120px
|
||||
height: 83px
|
||||
|
@ -185,28 +222,112 @@
|
|||
.gems .pulse
|
||||
@include animation(rewardPulse 0.25s infinite)
|
||||
|
||||
//- Footer
|
||||
|
||||
.modal-footer
|
||||
padding-bottom: 0
|
||||
|
||||
p.sign-up-poke
|
||||
color: white
|
||||
|
||||
.sign-up-button
|
||||
float: right
|
||||
margin: 2px 10px
|
||||
//- Footer - totals
|
||||
|
||||
#totals
|
||||
color: white
|
||||
width: 709px
|
||||
height: 96px
|
||||
background: transparent url(/images/pages/play/level/modal/xp_gems_parchment.png)
|
||||
position: relative
|
||||
text-align: left
|
||||
|
||||
.total-wrapper
|
||||
position: absolute
|
||||
top: 18px
|
||||
|
||||
&#xp-wrapper
|
||||
left: 117px
|
||||
width: 300px
|
||||
|
||||
&#gem-wrapper
|
||||
left: 529px
|
||||
|
||||
.total-label
|
||||
width: 90px
|
||||
|
||||
.total-count
|
||||
float: left
|
||||
font-size: 45px
|
||||
font-weight: bold
|
||||
color: rgb(40, 33, 22)
|
||||
margin-right: 12px
|
||||
|
||||
.total-label
|
||||
float: left
|
||||
color: rgb(103, 92, 76)
|
||||
text-transform: uppercase
|
||||
font-weight: bold
|
||||
font-family: 'Open Sans Condensed'
|
||||
font-size: 18px
|
||||
margin-top: 13px
|
||||
line-height: 18px
|
||||
|
||||
.xp-bar-outer
|
||||
background-color: rgb(40, 33, 22)
|
||||
border: 4px solid rgb(40, 33, 22)
|
||||
border-radius: 8px
|
||||
width: 150px
|
||||
height: 16px
|
||||
margin-top: 3px
|
||||
position: relative
|
||||
float: left
|
||||
|
||||
.xp-bar-already-achieved
|
||||
background-color: rgb(166, 213, 88)
|
||||
//background-color: white
|
||||
border-radius: 8px
|
||||
height: 100%
|
||||
position: absolute
|
||||
z-index: 1
|
||||
|
||||
.xp-bar-total
|
||||
background-color: rgb(253, 171, 45)
|
||||
border: 1px solid rgb(239, 177, 73)
|
||||
border-radius: 8px
|
||||
height: 100%
|
||||
position: absolute
|
||||
|
||||
|
||||
//- Footer - other stuff
|
||||
|
||||
.modal-footer
|
||||
// Negative bottom margin counteracts most of the extra the border image height.
|
||||
margin: 0 0 -80px 0
|
||||
padding: 0 20px
|
||||
text-align: center
|
||||
|
||||
.sign-up-poke
|
||||
width: 430px
|
||||
|
||||
.sign-up-blurb
|
||||
width: 175px
|
||||
font-family: 'Open Sans Condensed'
|
||||
font-weight: bold
|
||||
text-transform: uppercase
|
||||
font-size: 18px
|
||||
line-height: 18px
|
||||
text-align: left
|
||||
float: left
|
||||
margin: 5px 0 0 5px
|
||||
color: rgb(160, 150, 126)
|
||||
|
||||
.sign-up-button
|
||||
width: 250px
|
||||
height: 60px
|
||||
line-height: 30px
|
||||
margin: 0
|
||||
float: left
|
||||
|
||||
|
||||
.next-level-buttons
|
||||
float: right
|
||||
|
||||
.next-level-button
|
||||
display: block
|
||||
margin: 8px 10px
|
||||
width: 150px
|
||||
.next-level-button, .return-to-ladder-button
|
||||
width: 258px
|
||||
height: 60px
|
||||
line-height: 30px
|
||||
margin: 0 10px
|
||||
|
||||
.ladder-submission-view
|
||||
display: inline-block
|
||||
|
@ -223,7 +344,11 @@
|
|||
|
||||
.hour-of-code-done
|
||||
clear: both
|
||||
padding-top: 10px
|
||||
margin: 5px auto 0 auto
|
||||
padding: 10px
|
||||
background-color: rgba(22, 34, 30, 0.5)
|
||||
border-radius: 8px
|
||||
display: inline-block
|
||||
|
||||
strong
|
||||
color: white
|
||||
|
@ -241,23 +366,25 @@
|
|||
|
||||
html.no-borderimage
|
||||
#hero-victory-modal
|
||||
.modal-dialog
|
||||
margin-top: 251px
|
||||
.background-wrapper
|
||||
border: 0
|
||||
background: url("/images/pages/play/level/modal/victory_modal_background.png")
|
||||
height: 650px
|
||||
#victory-header
|
||||
margin-top: 40px
|
||||
left: 160px
|
||||
#victory-banner
|
||||
left: 0px
|
||||
top: 40px
|
||||
.modal-header
|
||||
height: 110px
|
||||
.modal-content
|
||||
height: 650px
|
||||
padding-bottom: 0
|
||||
.modal-footer
|
||||
bottom: 20px
|
||||
height: 713px
|
||||
|
||||
&.full-achievements
|
||||
@media only screen and (max-height: 720px)
|
||||
.modal-dialog
|
||||
margin-top: 175px
|
||||
#victory-header
|
||||
background: transparent
|
||||
@media only screen and (max-height: 640px)
|
||||
.modal-dialog
|
||||
margin-top: 121px
|
||||
#victory-header
|
||||
display: none
|
||||
|
||||
|
||||
body.ipad
|
||||
#hero-victory-modal
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
extends /templates/core/modal-base
|
||||
block modal-header-content
|
||||
img(src="/images/pages/play/level/modal/victory_modal_blue_banner.png")#victory-banner
|
||||
img(src="/images/pages/play/level/modal/victory_word.png")#victory-header.out
|
||||
#victory-header.out
|
||||
#victory-title
|
||||
if me.get('preferredLanguage').split('-')[0] == 'en'
|
||||
img(src="/images/pages/play/level/modal/victory_word.png", draggable="false")
|
||||
else
|
||||
h1(data-i18n="play_level.victory") Victory
|
||||
|
||||
block modal-body-content
|
||||
|
||||
|
@ -43,33 +47,41 @@ block modal-body-content
|
|||
.reward-text= animate ? 'New Item' : item.get('name')
|
||||
|
||||
block modal-footer-content
|
||||
#totals
|
||||
.total-wrapper#xp-wrapper
|
||||
.total-count#xp-total 0
|
||||
.total-label
|
||||
span.spr(data-i18n="play_level.victory_experience_gained") XP Gained
|
||||
| -
|
||||
span.spl.spr(data-i18n="general.player_level") Level
|
||||
span.level= me.level()
|
||||
.xp-bar-outer
|
||||
.xp-bar-already-achieved
|
||||
.xp-bar-total
|
||||
.total-wrapper#gem-wrapper
|
||||
.total-count#gem-total 0
|
||||
.total-label(data-i18n="play_level.victory_gems_gained") Gems Gained
|
||||
|
||||
if me.get('anonymous')
|
||||
p.sign-up-poke.hide
|
||||
button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="core/AuthModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress
|
||||
span(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account!
|
||||
.sign-up-poke.hide
|
||||
.sign-up-blurb(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account!
|
||||
button.btn.btn-illustrated.btn-warning.sign-up-button.btn-lg(data-toggle="coco-modal", data-target="core/AuthModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress
|
||||
|
||||
div#totals.pull-left
|
||||
span.spr Experience Gained:
|
||||
span#xp-total +0
|
||||
br
|
||||
span.spr Gems Gained:
|
||||
span#gem-total +0
|
||||
|
||||
button.btn.btn-warning.hide#saving-progress-label(disabled, data-i18n="play_level.victory_saving_progress") Saving Progress
|
||||
button.btn.btn-illustrated.btn-lg.btn-warning.hide#saving-progress-label(disabled, data-i18n="play_level.victory_saving_progress") Saving Progress
|
||||
|
||||
.next-level-buttons
|
||||
if readyToRank
|
||||
.ladder-submission-view
|
||||
else if level.get('type') === 'hero-ladder'
|
||||
button.btn.btn-primary.return-to-ladder-button(data-href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_return_to_ladder") Return to Ladder
|
||||
button.btn.btn-illustrated.btn-primary.btn-lg.return-to-ladder-button(data-href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_return_to_ladder") Return to Ladder
|
||||
else
|
||||
button.btn.btn-success.world-map-button.next-level-button.hide#continue-button(data-i18n="play_level.victory_play_continue") Continue
|
||||
button.btn.btn-illustrated.btn-success.btn-lg.world-map-button.next-level-button.hide#continue-button(data-i18n="play_level.victory_play_continue") Continue
|
||||
|
||||
if showHourOfCodeDoneButton
|
||||
.hour-of-code-done
|
||||
hr
|
||||
a.image-link(href="http://code.org/api/hour/finish")
|
||||
img(src="/images/level/csedweek-logo-final-small.jpg", alt="CS Ed Week Hour of Code", title="I'm finished with my Hour of Code", width=80)
|
||||
strong(data-i18n="play_level.victory_hour_of_code_done") Are You Done?
|
||||
a.text-link(href="http://code.org/api/hour/finish")
|
||||
span(data-i18n="play_level.victory_hour_of_code_done_yes") Yes, I'm finished with my Hour of Code!
|
||||
.clearfix
|
|
@ -9,6 +9,8 @@ ThangType = require 'models/ThangType'
|
|||
LadderSubmissionView = require 'views/play/common/LadderSubmissionView'
|
||||
AudioPlayer = require 'lib/AudioPlayer'
|
||||
CampaignOptions = require 'lib/CampaignOptions'
|
||||
User = require 'models/User'
|
||||
utils = require 'core/utils'
|
||||
|
||||
module.exports = class HeroVictoryModal extends ModalView
|
||||
id: 'hero-victory-modal'
|
||||
|
@ -36,6 +38,8 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
@listenToOnce @achievements, 'sync', @onAchievementsLoaded
|
||||
@readyToContinue = false
|
||||
@waitingToContinueSince = new Date()
|
||||
@previousXP = me.get 'points', true
|
||||
@previousLevel = me.level()
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'victory'
|
||||
|
||||
destroy: ->
|
||||
|
@ -47,6 +51,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
super()
|
||||
|
||||
onAchievementsLoaded: ->
|
||||
@$el.toggleClass 'full-achievements', @achievements.models.length is 3
|
||||
thangTypeOriginals = []
|
||||
achievementIDs = []
|
||||
for achievement in @achievements.models
|
||||
|
@ -133,6 +138,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
return unless @supermodel.finished()
|
||||
@playSelectionSound hero, true for original, hero of @thangTypes # Preload them
|
||||
@updateSavingProgressStatus()
|
||||
@updateXPBars 0
|
||||
@$el.find('#victory-header').delay(250).queue(->
|
||||
$(@).removeClass('out').dequeue()
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'victory-title-appear' # TODO: actually add this
|
||||
|
@ -196,7 +202,8 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
totalXP = @totalXPAnimated + newXP
|
||||
if totalXP isnt @lastTotalXP
|
||||
panel.textEl.text('+' + newXP)
|
||||
@XPEl.text('+' + totalXP)
|
||||
@XPEl.text(totalXP)
|
||||
@updateXPBars(totalXP)
|
||||
xpTrigger = 'xp-' + (totalXP % 6) # 6 xp sounds
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: xpTrigger, volume: 0.5 + ratio / 2
|
||||
@lastTotalXP = totalXP
|
||||
|
@ -205,7 +212,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
totalGems = @totalGemsAnimated + newGems
|
||||
if totalGems isnt @lastTotalGems
|
||||
panel.textEl.text('+' + newGems)
|
||||
@gemEl.text('+' + totalGems)
|
||||
@gemEl.text(totalGems)
|
||||
gemTrigger = 'gem-' + (parseInt(panel.number * ratio) % 4) # 4 gem sounds
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: gemTrigger, volume: 0.5 + ratio / 2
|
||||
@lastTotalGems = totalGems
|
||||
|
@ -237,6 +244,32 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
--t
|
||||
-0.5 * (t * (t - 2) - 1)
|
||||
|
||||
updateXPBars: (achievedXP) ->
|
||||
previousXP = @previousXP
|
||||
previousLevel = @previousLevel
|
||||
|
||||
currentXP = previousXP + achievedXP
|
||||
currentLevel = User.levelFromExp currentXP
|
||||
currentLevelXP = User.expForLevel currentLevel
|
||||
|
||||
nextLevel = currentLevel + 1
|
||||
nextLevelXP = User.expForLevel nextLevel
|
||||
|
||||
leveledUp = currentLevel > previousLevel
|
||||
totalXPNeeded = nextLevelXP - currentLevelXP
|
||||
alreadyAchievedPercentage = 100 * (previousXP - currentLevelXP) / totalXPNeeded
|
||||
alreadyAchievedPercentage = 0 if alreadyAchievedPercentage < 0 # In case of level up
|
||||
if leveledUp
|
||||
newlyAchievedPercentage = 100 * (currentXP - currentLevelXP) / totalXPNeeded
|
||||
else
|
||||
newlyAchievedPercentage = 100 * achievedXP / totalXPNeeded
|
||||
|
||||
xpEl = $('#xp-wrapper')
|
||||
xpBarJustEarned = xpEl.find('.xp-bar-already-achieved').css('width', alreadyAchievedPercentage + '%')
|
||||
xpBarTotal = xpEl.find('.xp-bar-total').css('width', (alreadyAchievedPercentage + newlyAchievedPercentage) + '%')
|
||||
levelLabel = xpEl.find('.level')
|
||||
utils.replaceText levelLabel, currentLevel
|
||||
|
||||
endSequentialAnimations: ->
|
||||
clearInterval @sequentialAnimationInterval
|
||||
@animationComplete = true
|
||||
|
|
|
@ -446,7 +446,7 @@ module.exports = class InventoryModal extends ModalView
|
|||
patchSession = patchMe = false
|
||||
patchSession ||= not _.isEqual inventory, sessionHeroConfig.inventory
|
||||
sessionHeroConfig.inventory = inventory
|
||||
if hero = @selectedHero.get('original')
|
||||
if hero = @selectedHero?.get('original')
|
||||
patchSession ||= not _.isEqual hero, sessionHeroConfig.thangType
|
||||
sessionHeroConfig.thangType = hero
|
||||
patchMe ||= not _.isEqual inventory, lastHeroConfig.inventory
|
||||
|
@ -527,8 +527,8 @@ module.exports = class InventoryModal extends ModalView
|
|||
onClickedSomewhere: (e) ->
|
||||
return if @destroyed
|
||||
@$el.find('.unlock-button').popover 'destroy'
|
||||
|
||||
|
||||
|
||||
|
||||
#- Dynamic portrait loading
|
||||
|
||||
onScrollUnequipped: ->
|
||||
|
|